/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Communicate with a peer using NFC-DEP, LLCP, SNEP. */ #pragma once #include <utils/RefBase.h> #include <utils/StrongPointer.h> #include "SyncEvent.h" #include "NfcJniUtil.h" #include <string> extern "C" { #include "nfa_p2p_api.h" } class P2pServer; class P2pClient; class NfaConn; #define MAX_NFA_CONNS_PER_SERVER 5 /***************************************************************************** ** ** Name: PeerToPeer ** ** Description: Communicate with a peer using NFC-DEP, LLCP, SNEP. ** *****************************************************************************/ class PeerToPeer { public: typedef unsigned int tJNI_HANDLE; /******************************************************************************* ** ** Function: PeerToPeer ** ** Description: Initialize member variables. ** ** Returns: None ** *******************************************************************************/ PeerToPeer (); /******************************************************************************* ** ** Function: ~PeerToPeer ** ** Description: Free all resources. ** ** Returns: None ** *******************************************************************************/ ~PeerToPeer (); /******************************************************************************* ** ** Function: getInstance ** ** Description: Get the singleton PeerToPeer object. ** ** Returns: Singleton PeerToPeer object. ** *******************************************************************************/ static PeerToPeer& getInstance(); /******************************************************************************* ** ** Function: initialize ** ** Description: Initialize member variables. ** ** Returns: None ** *******************************************************************************/ void initialize (); /******************************************************************************* ** ** Function: llcpActivatedHandler ** ** Description: Receive LLLCP-activated event from stack. ** nat: JVM-related data. ** activated: Event data. ** ** Returns: None ** *******************************************************************************/ void llcpActivatedHandler (nfc_jni_native_data* nativeData, tNFA_LLCP_ACTIVATED& activated); /******************************************************************************* ** ** Function: llcpDeactivatedHandler ** ** Description: Receive LLLCP-deactivated event from stack. ** nat: JVM-related data. ** deactivated: Event data. ** ** Returns: None ** *******************************************************************************/ void llcpDeactivatedHandler (nfc_jni_native_data* nativeData, tNFA_LLCP_DEACTIVATED& deactivated); void llcpFirstPacketHandler(nfc_jni_native_data* nativeData); /******************************************************************************* ** ** Function: connectionEventHandler ** ** Description: Receive events from the stack. ** event: Event code. ** eventData: Event data. ** ** Returns: None ** *******************************************************************************/ void connectionEventHandler (UINT8 event, tNFA_CONN_EVT_DATA* eventData); /******************************************************************************* ** ** 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 registerServer (tJNI_HANDLE jniHandle, const char* serviceName); /******************************************************************************* ** ** Function: deregisterServer ** ** Description: Stop a P2pServer from listening for peer. ** ** Returns: True if ok. ** *******************************************************************************/ bool deregisterServer (tJNI_HANDLE jniHandle); /******************************************************************************* ** ** 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 accept (tJNI_HANDLE serverJniHandle, tJNI_HANDLE connJniHandle, int maxInfoUnit, int recvWindow); /******************************************************************************* ** ** 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 createClient (tJNI_HANDLE jniHandle, UINT16 miu, UINT8 rw); /******************************************************************************* ** ** Function: connectConnOriented ** ** Description: Establish a connection-oriented connection to a peer. ** jniHandle: Connection handle. ** serviceName: Peer's service name. ** ** Returns: True if ok. ** *******************************************************************************/ bool connectConnOriented (tJNI_HANDLE jniHandle, const char* serviceName); /******************************************************************************* ** ** Function: connectConnOriented ** ** Description: Establish a connection-oriented connection to a peer. ** jniHandle: Connection handle. ** destinationSap: Peer's service access point. ** ** Returns: True if ok. ** *******************************************************************************/ bool connectConnOriented (tJNI_HANDLE jniHandle, UINT8 destinationSap); /******************************************************************************* ** ** Function: send ** ** Description: Send data to peer. ** jniHandle: Handle of connection. ** buffer: Buffer of data. ** bufferLen: Length of data. ** ** Returns: True if ok. ** *******************************************************************************/ bool send (tJNI_HANDLE jniHandle, UINT8* buffer, UINT16 bufferLen); /******************************************************************************* ** ** 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 receive (tJNI_HANDLE jniHandle, UINT8* buffer, UINT16 bufferLen, UINT16& actualLen); /******************************************************************************* ** ** Function: disconnectConnOriented ** ** Description: Disconnect a connection-oriented connection with peer. ** jniHandle: Handle of connection. ** ** Returns: True if ok. ** *******************************************************************************/ bool disconnectConnOriented (tJNI_HANDLE jniHandle); /******************************************************************************* ** ** Function: getRemoteMaxInfoUnit ** ** Description: Get peer's max information unit. ** jniHandle: Handle of the connection. ** ** Returns: Peer's max information unit. ** *******************************************************************************/ UINT16 getRemoteMaxInfoUnit (tJNI_HANDLE jniHandle); /******************************************************************************* ** ** Function: getRemoteRecvWindow ** ** Description: Get peer's receive window size. ** jniHandle: Handle of the connection. ** ** Returns: Peer's receive window size. ** *******************************************************************************/ UINT8 getRemoteRecvWindow (tJNI_HANDLE jniHandle); /******************************************************************************* ** ** Function: setP2pListenMask ** ** Description: Sets the p2p listen technology mask. ** p2pListenMask: the p2p listen mask to be set? ** ** Returns: None ** *******************************************************************************/ void setP2pListenMask (tNFA_TECHNOLOGY_MASK p2pListenMask); /******************************************************************************* ** ** Function: getP2pListenMask ** ** Description: Get the set of technologies that P2P is listening. ** ** Returns: Set of technologies. ** *******************************************************************************/ tNFA_TECHNOLOGY_MASK getP2pListenMask (); /******************************************************************************* ** ** Function: resetP2pListenMask ** ** Description: Reset the p2p listen technology mask to initial value. ** ** Returns: None. ** *******************************************************************************/ void resetP2pListenMask (); /******************************************************************************* ** ** Function: enableP2pListening ** ** Description: Start/stop polling/listening to peer that supports P2P. ** isEnable: Is enable polling/listening? ** ** Returns: None ** *******************************************************************************/ void enableP2pListening (bool isEnable); /******************************************************************************* ** ** Function: handleNfcOnOff ** ** Description: Handle events related to turning NFC on/off by the user. ** isOn: Is NFC turning on? ** ** Returns: None ** *******************************************************************************/ void handleNfcOnOff (bool isOn); /******************************************************************************* ** ** Function: getNextJniHandle ** ** Description: Get a new JNI handle. ** ** Returns: A new JNI handle. ** *******************************************************************************/ tJNI_HANDLE getNewJniHandle (); /******************************************************************************* ** ** Function: nfaServerCallback ** ** Description: Receive LLCP-related events from the stack. ** p2pEvent: Event code. ** eventData: Event data. ** ** Returns: None ** *******************************************************************************/ static void nfaServerCallback (tNFA_P2P_EVT p2pEvent, tNFA_P2P_EVT_DATA *eventData); /******************************************************************************* ** ** Function: nfaClientCallback ** ** Description: Receive LLCP-related events from the stack. ** p2pEvent: Event code. ** eventData: Event data. ** ** Returns: None ** *******************************************************************************/ static void nfaClientCallback (tNFA_P2P_EVT p2pEvent, tNFA_P2P_EVT_DATA *eventData); private: static const int sMax = 10; static PeerToPeer sP2p; // Variables below only accessed from a single thread UINT16 mRemoteWKS; // Peer's well known services bool mIsP2pListening; // If P2P listening is enabled or not tNFA_TECHNOLOGY_MASK mP2pListenTechMask; // P2P Listen mask // Variable below is protected by mNewJniHandleMutex tJNI_HANDLE mNextJniHandle; // Variables below protected by mMutex // A note on locking order: mMutex in PeerToPeer is *ALWAYS* // locked before any locks / guards in P2pServer / P2pClient Mutex mMutex; android::sp<P2pServer> mServers [sMax]; android::sp<P2pClient> mClients [sMax]; // Synchronization variables SyncEvent mSetTechEvent; // completion event for NFA_SetP2pListenTech() SyncEvent mSnepDefaultServerStartStopEvent; // completion event for NFA_SnepStartDefaultServer(), NFA_SnepStopDefaultServer() SyncEvent mSnepRegisterEvent; // completion event for NFA_SnepRegisterClient() Mutex mDisconnectMutex; // synchronize the disconnect operation Mutex mNewJniHandleMutex; // synchronize the creation of a new JNI handle /******************************************************************************* ** ** Function: ndefTypeCallback ** ** Description: Receive NDEF-related events from the stack. ** ndefEvent: Event code. ** eventData: Event data. ** ** Returns: None ** *******************************************************************************/ static void ndefTypeCallback (tNFA_NDEF_EVT event, tNFA_NDEF_EVT_DATA *evetnData); /******************************************************************************* ** ** Function: findServer ** ** Description: Find a PeerToPeer object by connection handle. ** nfaP2pServerHandle: Connectin handle. ** ** Returns: PeerToPeer object. ** *******************************************************************************/ android::sp<P2pServer> findServerLocked (tNFA_HANDLE nfaP2pServerHandle); /******************************************************************************* ** ** Function: findServer ** ** Description: Find a PeerToPeer object by connection handle. ** serviceName: service name. ** ** Returns: PeerToPeer object. ** *******************************************************************************/ android::sp<P2pServer> findServerLocked (tJNI_HANDLE jniHandle); /******************************************************************************* ** ** Function: findServer ** ** Description: Find a PeerToPeer object by service name ** serviceName: service name. ** ** Returns: PeerToPeer object. ** *******************************************************************************/ android::sp<P2pServer> findServerLocked (const char *serviceName); /******************************************************************************* ** ** Function: removeServer ** ** Description: Free resources related to a server. ** jniHandle: Connection handle. ** ** Returns: None ** *******************************************************************************/ void removeServer (tJNI_HANDLE jniHandle); /******************************************************************************* ** ** Function: removeConn ** ** Description: Free resources related to a connection. ** jniHandle: Connection handle. ** ** Returns: None ** *******************************************************************************/ void removeConn (tJNI_HANDLE jniHandle); /******************************************************************************* ** ** Function: createDataLinkConn ** ** Description: Establish 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 createDataLinkConn (tJNI_HANDLE jniHandle, const char* serviceName, UINT8 destinationSap); /******************************************************************************* ** ** Function: findClient ** ** Description: Find a PeerToPeer object with a client connection handle. ** nfaConnHandle: Connection handle. ** ** Returns: PeerToPeer object. ** *******************************************************************************/ android::sp<P2pClient> findClient (tNFA_HANDLE nfaConnHandle); /******************************************************************************* ** ** Function: findClient ** ** Description: Find a PeerToPeer object with a client connection handle. ** jniHandle: Connection handle. ** ** Returns: PeerToPeer object. ** *******************************************************************************/ android::sp<P2pClient> findClient (tJNI_HANDLE jniHandle); /******************************************************************************* ** ** Function: findClientCon ** ** Description: Find a PeerToPeer object with a client connection handle. ** nfaConnHandle: Connection handle. ** ** Returns: PeerToPeer object. ** *******************************************************************************/ android::sp<P2pClient> findClientCon (tNFA_HANDLE nfaConnHandle); /******************************************************************************* ** ** Function: findConnection ** ** Description: Find a PeerToPeer object with a connection handle. ** nfaConnHandle: Connection handle. ** ** Returns: PeerToPeer object. ** *******************************************************************************/ android::sp<NfaConn> findConnection (tNFA_HANDLE nfaConnHandle); /******************************************************************************* ** ** Function: findConnection ** ** Description: Find a PeerToPeer object with a connection handle. ** jniHandle: Connection handle. ** ** Returns: PeerToPeer object. ** *******************************************************************************/ android::sp<NfaConn> findConnection (tJNI_HANDLE jniHandle); }; /***************************************************************************** ** ** Name: NfaConn ** ** Description: Store information about a connection related to a peer. ** *****************************************************************************/ class NfaConn : public android::RefBase { public: tNFA_HANDLE mNfaConnHandle; // NFA handle of the P2P connection PeerToPeer::tJNI_HANDLE mJniHandle; // JNI handle of the P2P connection UINT16 mMaxInfoUnit; UINT8 mRecvWindow; UINT16 mRemoteMaxInfoUnit; UINT8 mRemoteRecvWindow; SyncEvent mReadEvent; // event for reading SyncEvent mCongEvent; // event for congestion SyncEvent mDisconnectingEvent; // event for disconnecting /******************************************************************************* ** ** Function: NfaConn ** ** Description: Initialize member variables. ** ** Returns: None ** *******************************************************************************/ NfaConn(); }; /***************************************************************************** ** ** Name: P2pServer ** ** Description: Store information about an in-bound connection from a peer. ** *****************************************************************************/ class P2pServer : public android::RefBase { public: static const std::string sSnepServiceName; tNFA_HANDLE mNfaP2pServerHandle; // NFA p2p handle of local server PeerToPeer::tJNI_HANDLE mJniHandle; // JNI Handle SyncEvent mRegServerEvent; // for NFA_P2pRegisterServer() SyncEvent mConnRequestEvent; // for accept() std::string mServiceName; /******************************************************************************* ** ** Function: P2pServer ** ** Description: Initialize member variables. ** ** Returns: None ** *******************************************************************************/ P2pServer (PeerToPeer::tJNI_HANDLE jniHandle, const char* serviceName); /******************************************************************************* ** ** Function: registerWithStack ** ** Description: Register this server with the stack. ** ** Returns: True if ok. ** *******************************************************************************/ bool registerWithStack(); /******************************************************************************* ** ** 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 accept (PeerToPeer::tJNI_HANDLE serverJniHandle, PeerToPeer::tJNI_HANDLE connJniHandle, int maxInfoUnit, int recvWindow); /******************************************************************************* ** ** Function: unblockAll ** ** Description: Unblocks all server connections ** ** Returns: True if ok. ** *******************************************************************************/ void unblockAll(); /******************************************************************************* ** ** Function: findServerConnection ** ** Description: Find a P2pServer that has the handle. ** nfaConnHandle: NFA connection handle. ** ** Returns: P2pServer object. ** *******************************************************************************/ android::sp<NfaConn> findServerConnection (tNFA_HANDLE nfaConnHandle); /******************************************************************************* ** ** Function: findServerConnection ** ** Description: Find a P2pServer that has the handle. ** jniHandle: JNI connection handle. ** ** Returns: P2pServer object. ** *******************************************************************************/ android::sp<NfaConn> findServerConnection (PeerToPeer::tJNI_HANDLE jniHandle); /******************************************************************************* ** ** Function: removeServerConnection ** ** Description: Remove a server connection with the provided handle. ** jniHandle: JNI connection handle. ** ** Returns: True if connection found and removed. ** *******************************************************************************/ bool removeServerConnection(PeerToPeer::tJNI_HANDLE jniHandle); private: Mutex mMutex; // mServerConn is protected by mMutex android::sp<NfaConn> mServerConn[MAX_NFA_CONNS_PER_SERVER]; /******************************************************************************* ** ** Function: allocateConnection ** ** Description: Allocate a new connection to accept on ** jniHandle: JNI connection handle. ** ** Returns: Allocated connection object ** NULL if the maximum number of connections was reached ** *******************************************************************************/ android::sp<NfaConn> allocateConnection (PeerToPeer::tJNI_HANDLE jniHandle); }; /***************************************************************************** ** ** Name: P2pClient ** ** Description: Store information about an out-bound connection to a peer. ** *****************************************************************************/ class P2pClient : public android::RefBase { public: tNFA_HANDLE mNfaP2pClientHandle; // NFA p2p handle of client bool mIsConnecting; // Set true while connecting android::sp<NfaConn> mClientConn; SyncEvent mRegisteringEvent; // For client registration SyncEvent mConnectingEvent; // for NFA_P2pConnectByName or Sap() SyncEvent mSnepEvent; // To wait for SNEP completion /******************************************************************************* ** ** Function: P2pClient ** ** Description: Initialize member variables. ** ** Returns: None ** *******************************************************************************/ P2pClient (); /******************************************************************************* ** ** Function: ~P2pClient ** ** Description: Free all resources. ** ** Returns: None ** *******************************************************************************/ ~P2pClient (); /******************************************************************************* ** ** Function: unblock ** ** Description: Unblocks any threads that are locked on this connection ** ** Returns: None ** *******************************************************************************/ void unblock(); };