JNIEXPORT void JNICALL Java_com_intel_bluetooth_BluetoothStackBlueZDBus_connectionRfWrite__J_3BII (JNIEnv* env, jobject peer, jlong handle, jbyteArray b, jint off, jint len) { if (b == NULL) { throwRuntimeException(env, "Invalid argument"); return; } jbyte *bytes = (*env)->GetByteArrayElements(env, b, 0); if (bytes == NULL) { throwRuntimeException(env, "Invalid argument"); return; } int done = 0; while(done < len) { int count = send(handle, (char *)(bytes + off + done), len - done, 0); if (count < 0) { throwIOException(env, "Failed to write. [%d] %s", errno, strerror(errno)); break; } if (isCurrentThreadInterrupted(env, peer)) { break; } done += count; } (*env)->ReleaseByteArrayElements(env, b, bytes, 0); }
JNIEXPORT jlong JNICALL Java_com_intel_bluetooth_BluetoothStackBlueZ_l2ServerAcceptAndOpenServerConnection (JNIEnv* env, jobject peer, jlong handle) { struct sockaddr_l2 remoteAddr; socklen_t remoteAddrLen = sizeof(remoteAddr); int client_socket = SOCKET_ERROR; do { client_socket = accept(handle, (struct sockaddr*)&remoteAddr, &remoteAddrLen); if (SOCKET_ERROR == client_socket) { if (errno == EWOULDBLOCK) { if (isCurrentThreadInterrupted(env, peer)) { return 0; } if (!threadSleep(env, 100)) { return 0; } continue; } else { throwIOException(env, "Failed to accept L2CAP client connection. [%d] %s", errno, strerror(errno)); return 0; } } } while (SOCKET_ERROR == client_socket); return client_socket; }
JNIEXPORT jint JNICALL Java_com_intel_bluetooth_BluetoothStackBlueZDBus_connectionRfRead (JNIEnv* env, jobject peer, jlong handle, jbyteArray b, jint off, jint len ) { if (b == NULL) { throwRuntimeException(env, "Invalid argument"); return 0; } jbyte *bytes = (*env)->GetByteArrayElements(env, b, 0); if (bytes == NULL) { throwRuntimeException(env, "Invalid argument"); return 0; } int done = 0; while (done == 0) { int flags = MSG_DONTWAIT; int count = recv(handle, (char *)(bytes + off + done), len - done, flags); if (count < 0) { if (errno == EAGAIN) { // Try again for non-blocking operation count = 0; Edebug("no data available for read"); } else if (errno == ECONNRESET) { //104 Connection reset by peer debug("Connection closed, Connection reset by peer"); // See InputStream.read(); done = -1; goto rfReadEnd; } else { throwIOException(env, "Failed to read. [%d] %s", errno, strerror(errno)); done = 0; goto rfReadEnd; } } else if (count == 0) { debug("Connection closed"); if (done == 0) { // See InputStream.read(); done = -1; } goto rfReadEnd; } done += count; if (isCurrentThreadInterrupted(env, peer)) { done = 0; goto rfReadEnd; } if (done == 0) { // Sleep while not avalable bool available = false; do { struct pollfd fds; int timeout = 500; // milliseconds memset(&fds, 0, sizeof(fds)); fds.fd = handle; fds.events = POLLIN | POLLHUP | POLLERR;// | POLLRDHUP; fds.revents = 0; //Edebug("poll: wait"); int poll_rc = poll(&fds, 1, timeout); if (poll_rc > 0) { if (fds.revents & (POLLHUP | POLLERR /* | POLLRDHUP */)) { debug("Stream socket peer closed connection"); done = -1; goto rfReadEnd; } else if (fds.revents & POLLNVAL) { // socket closed... done = -1; goto rfReadEnd; } else if (fds.revents & POLLIN) { //Edebug("poll: data to read available"); available = true; } else { Edebug("poll: revents %i", fds.revents); } } else if (poll_rc == -1) { //Edebug("poll: call error %i", errno); throwIOException(env, "Failed to poll. [%d] %s", errno, strerror(errno)); done = 0; goto rfReadEnd; } else { //Edebug("poll: call timed out"); } if (isCurrentThreadInterrupted(env, peer)) { done = -1; goto rfReadEnd; } } while (!available); } } rfReadEnd: (*env)->ReleaseByteArrayElements(env, b, bytes, 0); return done; }
JNIEXPORT jint JNICALL Java_com_intel_bluetooth_BluetoothStackBlueZ_l2Receive (JNIEnv* env, jobject peer, jlong handle, jbyteArray inBuf) { #ifdef BLUECOVE_L2CAP_MTU_TRUNCATE struct l2cap_options opt; if (!l2Get_options(env, handle, &opt)) { return 0; } #endif //BLUECOVE_L2CAP_MTU_TRUNCATE bool dataReady = false; while(!dataReady) { struct pollfd fds; int timeout = 10; // milliseconds fds.fd = handle; fds.events = POLLIN | POLLHUP | POLLERR;// | POLLRDHUP; fds.revents = 0; if (poll(&fds, 1, timeout) > 0) { if (fds.revents & (POLLHUP | POLLERR /*| POLLRDHUP*/)) { throwIOException(env, "Peer closed connection"); return 0; } else if (fds.revents & POLLIN) { dataReady = true; } } if(isCurrentThreadInterrupted(env, peer)) { return 0; } } jbyte *bytes = (*env)->GetByteArrayElements(env, inBuf, 0); size_t inBufLen = (size_t)(*env)->GetArrayLength(env, inBuf); int readLen = inBufLen; #ifdef BLUECOVE_L2CAP_MTU_TRUNCATE if (readLen > opt.imtu) { readLen = opt.imtu; } #endif //BLUECOVE_L2CAP_MTU_TRUNCATE #ifdef BLUECOVE_L2CAP_USE_MSG int flags = 0; iovec iov; msghdr msg; memset((void*)&iov, 0, sizeof(iov)); memset((void*)&msg, 0, sizeof(msg)); iov.iov_base = bytes; iov.iov_len = readLen; msg.msg_iov = &iov; msg.msg_iovlen = 1; int count = recvmsg(handle, &msg, flags); #else int count = recv(handle, (char *)bytes, readLen, 0); #endif //BLUECOVE_L2CAP_USE_MSG if (count < 0) { throwIOException(env, "Failed to read. [%d] %s", errno, strerror(errno)); count = 0; } (*env)->ReleaseByteArrayElements(env, inBuf, bytes, 0); debug("receive[] returns %i", count); return count; }
JNIEXPORT jint JNICALL Java_com_intel_bluetooth_BluetoothStackWIDCOMM_l2Receive (JNIEnv *env, jobject peer, jlong handle, jbyteArray inBuf) { WIDCOMMStackL2CapConn* l2c = validL2CapConnHandle(env, handle); if (l2c == NULL) { return 0; } debug(("l2(%i) receive(byte[])", l2c->internalHandle)); if ((!l2c->isConnected ) && (l2c->receiveBuffer.available() < sizeof(UINT16))) { throwIOException(env, cCONNECTION_IS_CLOSED); return 0; } if (l2c->receiveBuffer.isOverflown()) { throwIOException(env, "Receive buffer overflown"); return 0; } HANDLE hEvents[2]; hEvents[0] = l2c->hConnectionEvent; hEvents[1] = l2c->hDataReceivedEvent; int paketLengthSize = l2c->receiveBuffer.sizeof_len(); while ((stack != NULL) && l2c->isConnected && (l2c->receiveBuffer.available() <= paketLengthSize)) { debug(("receive[] waits for data")); DWORD rc = WaitForMultipleObjects(2, hEvents, FALSE, 500); if (rc == WAIT_FAILED) { throwRuntimeException(env, "WaitForMultipleObjects"); return 0; } debug(("receive[] waits returns %s", waitResultsString(rc))); if (isCurrentThreadInterrupted(env, peer, "receive")) { return 0; } } if ((stack == NULL) || ((!l2c->isConnected) && (l2c->receiveBuffer.available() <= paketLengthSize)) ) { throwIOException(env, cCONNECTION_CLOSED); return 0; } int count = l2c->receiveBuffer.available(); if (count < paketLengthSize) { throwIOException(env, "Receive buffer corrupted (1)"); return 0; } int paketLength = 0; int done = l2c->receiveBuffer.read_len(&paketLength); if ((done != paketLengthSize) || (paketLength > (count - paketLengthSize))) { throwIOException(env, "Receive buffer corrupted (2)"); return 0; } if (paketLength == 0) { return 0; } jbyte *bytes = env->GetByteArrayElements(inBuf, 0); UINT16 inBufLen = (UINT16)env->GetArrayLength(inBuf); int readLen = paketLength; if (readLen > inBufLen) { readLen = inBufLen; } if (readLen > l2c->receiveMTU) { readLen = l2c->receiveMTU; } done = l2c->receiveBuffer.read(bytes, readLen); if (done != readLen) { throwIOException(env, "Receive buffer corrupted (3)"); } if (done < paketLength) { // the rest will be discarded. int skip = paketLength - done; if (skip != l2c->receiveBuffer.skip(skip)) { throwIOException(env, "Receive buffer corrupted (4)"); } } env->ReleaseByteArrayElements(inBuf, bytes, 0); debug(("receive[] returns %i", done)); return done; }
JNIEXPORT jlong JNICALL Java_com_intel_bluetooth_BluetoothStackWIDCOMM_l2ServerAcceptAndOpenServerConnection (JNIEnv *env, jobject peer, jlong handle) { WIDCOMMStackL2CapServer* srv = validL2CapServerHandle(env, handle); if (srv == NULL) { return 0; } if (srv->sdpService == NULL) { throwIOException(env, cCONNECTION_CLOSED); return 0; } if (!srv->finalizeSDPRecord(env)) { return 0; } #ifdef BWT_SINCE_SDK_6_0_1 srv->sdpService->CommitRecord(); #endif EnterCriticalSection(&stack->csCommIf); if (stack == NULL) { throwInterruptedIOException(env, cSTACK_CLOSED); } WIDCOMMStackL2CapConn* l2c = stack->createL2CapConn(); if (l2c == NULL) { throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_NO_RESOURCES, "No free connections Objects in Pool"); LeaveCriticalSection(&stack->csCommIf); return 0; } srv->addClient(l2c); l2c->receiveMTU = srv->receiveMTU; l2c->transmitMTU = srv->transmitMTU; BOOL rc = l2c->Listen(&(srv->l2CapIf)); if (stack != NULL) { LeaveCriticalSection(&stack->csCommIf); } if (!rc) { throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_FAILED_NOINFO, "Failed to Listen"); accept_l2_server_return 0; } HANDLE hEvents[2]; hEvents[0] = l2c->hConnectionEvent; hEvents[1] = srv->hConnectionEvent; debug(("l2s(%i) l2(%i) L2CAP server waits for connection", srv->internalHandle, l2c->internalHandle)); long incomingConnectionCountWas = incomingL2CAPConnectionCount; while ((stack != NULL) && (!srv->isClosing) && (!l2c->isConnected) && (!l2c->isDisconnected) && (srv->sdpService != NULL)) { DWORD rc = WaitForMultipleObjects(2, hEvents, FALSE, 500); if (rc == WAIT_FAILED) { throwRuntimeException(env, "WaitForSingleObject"); accept_l2_server_return 0; } if ((stack != NULL) && (incomingConnectionCountWas != incomingL2CAPConnectionCount)) { debug(("L2CAP server incomingConnectionCount %i", incomingL2CAPConnectionCount)); incomingConnectionCountWas = incomingL2CAPConnectionCount; } if (isCurrentThreadInterrupted(env, peer, "accept")) { accept_l2_server_return 0; } } if (stack == NULL) { throwInterruptedIOException(env, cSTACK_CLOSED); return 0; } if (!l2c->isConnected) { if (srv->isClosing || (srv->sdpService == NULL)) { throwInterruptedIOException(env, cCONNECTION_CLOSED); } else if (l2c->isDisconnected) { throwIOException(env, "Connection error"); } else { throwIOException(env, "Failed to connect"); } accept_l2_server_return 0; } debug(("l2s(%i) l2(%i) L2CAP server connection made", srv->internalHandle, l2c->internalHandle)); l2c->selectConnectionTransmitMTU(env); return l2c->internalHandle; }
JNIEXPORT jlong JNICALL Java_com_intel_bluetooth_BluetoothStackWIDCOMM_l2OpenClientConnectionImpl (JNIEnv *env, jobject peer, jlong address, jint channel, jboolean authenticate, jboolean encrypt, jint receiveMTU, jint transmitMTU, jint timeout) { BD_ADDR bda; LongToBcAddr(address, bda); WIDCOMMStackL2CapConn* l2c = NULL; EnterCriticalSection(&stack->csCommIf); //vc6 __try { l2c = stack->createL2CapConn(); if (l2c == NULL) { throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_NO_RESOURCES, "No free connections Objects in Pool"); open_l2client_return 0; } debug(("l2(%i) L2CapConn handle created", l2c->internalHandle)); if ((l2c->hConnectionEvent == NULL) || (l2c->hDataReceivedEvent == NULL)) { throwRuntimeException(env, "fails to CreateEvent"); open_l2client_return 0; } debug(("L2CapConn channel 0x%X", channel)); //debug(("AssignPsmValue"); CL2CapIf *l2CapIf = new CL2CapIf(); l2c->pL2CapIf = l2CapIf; if (!l2CapIf->AssignPsmValue(&(l2c->service_guid), (UINT16)channel)) { // What GUID do we need in call to CL2CapIf.AssignPsmValue() if we don't have any? // NEED This for stack version 3.0.1.905 // TODO test on v5.0.1.2800 and v4.0.1.2900 GUID any_client_service_guid = {2970356705 , 4369, 4369, {17 , 17, 17 , 17, 17, 17 , 0, 1}}; memcpy(&(l2c->service_guid), &any_client_service_guid, sizeof(GUID)); if (!l2CapIf->AssignPsmValue(&(l2c->service_guid), (UINT16)channel)) { throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_UNKNOWN_PSM, "failed to assign PSM 0x%X", (UINT16)channel); open_l2client_return 0; } } l2CapIf->Register(); UINT8 sec_level = BTM_SEC_NONE; if (authenticate) { sec_level = BTM_SEC_OUT_AUTHENTICATE; } if (encrypt) { sec_level = sec_level | BTM_SEC_OUT_ENCRYPT; } BT_CHAR *p_service_name; #ifdef _WIN32_WCE p_service_name = (BT_CHAR*)L"bluecovesrv"; #else // _WIN32_WCE p_service_name = "bluecovesrv"; #endif // #else // _WIN32_WCE if (!l2CapIf->SetSecurityLevel(p_service_name, sec_level, FALSE)) { throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_SECURITY_BLOCK, "Error setting security level"); open_l2client_return 0; } //debug(("OpenL2CAPClient")); l2c->transmitMTU = (UINT16)transmitMTU; l2c->receiveMTU = (UINT16)receiveMTU; BOOL rc = l2c->Connect(l2CapIf, bda, l2c->receiveMTU); if (!rc) { throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_FAILED_NOINFO, "Failed to Connect"); open_l2client_return 0; } //debug(("waitFor Connection signal"); DWORD waitStart = GetTickCount(); while ((stack != NULL) && (!l2c->isConnected) && (!l2c->isDisconnected)) { DWORD rc = WaitForSingleObject(l2c->hConnectionEvent, 500); if (rc == WAIT_FAILED) { throwRuntimeException(env, "WaitForSingleObject"); open_l2client_return 0; } if (isCurrentThreadInterrupted(env, peer, "connect")) { open_l2client_return 0; } if ((timeout > 0) && ((GetTickCount() - waitStart) > (DWORD)timeout)) { throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_TIMEOUT, "Connection timeout"); open_l2client_return 0; } } if (stack == NULL) { throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_FAILED_NOINFO, "Failed to connect"); open_l2client_return 0; } if (!l2c->isConnected) { throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_FAILED_NOINFO, "Failed to connect"); open_l2client_return 0; } debug(("l2(%i) l2Client connected", l2c->internalHandle)); l2c->selectConnectionTransmitMTU(env); jlong handle = l2c->internalHandle; l2c = NULL; open_l2client_return handle; /* vc6 } __finally {} */ }