I am working on a VPN app in swift 5. We are using NEVPNManager to handle all VPN configs. One of the features we would like is to measure the user's usage data while they are connected to our VPN. How can we do this ?
NEVPNManager doesn't offer any method that fulfil your requirement. Following is the solution is personally use in application.
Solution: Search for the suitable Network Interface and start reading the In and Out bytes.
en0 refers to Wifi
pdp_ip refers to Cellular network
+ (NSDictionary *) DataCounters{
struct ifaddrs *addrs;
const struct ifaddrs *cursor;
u_int32_t WiFiSent = 0;
u_int32_t WiFiReceived = 0;
u_int32_t WWANSent = 0;
u_int32_t WWANReceived = 0;
if (getifaddrs(&addrs) == 0)
{
cursor = addrs;
while (cursor != NULL)
{
if (cursor->ifa_addr->sa_family == AF_LINK)
{
// name of interfaces:
// en0 is WiFi
// pdp_ip0 is WWAN
NSString *name = [NSString stringWithFormat:#"%s",cursor->ifa_name];
if ([name hasPrefix:#"en"])
{
const struct if_data *ifa_data = (struct if_data *)cursor->ifa_data;
if(ifa_data != NULL)
{
WiFiSent += ifa_data->ifi_obytes;
WiFiReceived += ifa_data->ifi_ibytes;
}
}
if ([name hasPrefix:#"pdp_ip"])
{
const struct if_data *ifa_data = (struct if_data *)cursor->ifa_data;
if(ifa_data != NULL)
{
WWANSent += ifa_data->ifi_obytes;
WWANReceived += ifa_data->ifi_ibytes;
}
}
}
cursor = cursor->ifa_next;
}
freeifaddrs(addrs);
}
return #{DataCounterKeyWiFiSent:[NSNumber numberWithUnsignedInt:WiFiSent],
DataCounterKeyWiFiReceived:[NSNumber numberWithUnsignedInt:WiFiReceived],
DataCounterKeyWWANSent:[NSNumber numberWithUnsignedInt:WWANSent],
DataCounterKeyWWANReceived:[NSNumber numberWithUnsignedInt:WWANReceived]};}
Related
In my project I need to detect multiple gestures, I made a .gbd file with 2 continuous gestures. I can detect the continuous gesture when the .gbd file had one gesture. When there is 2 gestures I am unable to read any one gesture. Do any one know the reason? Here I post my code. I used Body basics example from sdk, and added necessary functions separately to avoid memory leakage.
//separate function to initialize database, vgb frame source and vgb frame reader
void CBodyBasics::InitializeVGB()
{
HRESULT hr;
std::wstring sDbFile = L"ContinuousGestures.gbd";
hr = CreateVisualGestureBuilderDatabaseInstanceFromFile(sDbFile.c_str(), &m_pGestureDatabase);
if (SUCCEEDED(hr))
{
OutputDebugString(L"Success DB\n");
}
else
{
OutputDebugString(L"Failure DB\n");
}
for (int i = 0; i < BODY_COUNT; i++)
{
// Source
hr = CreateVisualGestureBuilderFrameSource(m_pKinectSensor, 0, &m_pVGBFrameSource[i]);
if (SUCCEEDED(hr))
{
OutputDebugString(L"Source created\n");
}
else
{
OutputDebugString(L"Soure creation failed\n");
}
// Reader
hr = m_pVGBFrameSource[i]->OpenReader(&m_pVGBFrameReader[i]);
if (SUCCEEDED(hr))
{
OutputDebugString(L"reader opened\n");
}
else
{
OutputDebugString(L"No reader\n");
}
}
}
//function to find the available gesture count, add the available gestures to source
void CBodyBasics::CheckGestureMultiple()
{
HRESULT hr;
hr = m_pGestureDatabase->get_AvailableGesturesCount(&iGestureCount);
//gesture count
if (SUCCEEDED(hr))
{
OutputDebugString(L"gesture #\n");
}
else
{
OutputDebugString(L"0 gesture\n");
}
StringCchPrintf(smessage, _countof(smessage), L"Gesture Count %d \n", iGestureCount);
OutputDebugString(smessage);
hr = m_pGestureDatabase->get_AvailableGestures(iGestureCount, m_pgesturelist);
//gesture list
if (SUCCEEDED(hr) && m_pgesturelist != nullptr)
{
OutputDebugString(L"received available gestures\n");
GestureType mtype;
WCHAR sName[260];
for (int i = 0; i < iGestureCount; ++i)
{
hr = m_pgesturelist[i]->get_GestureType(&mtype);
//gesture type
if (SUCCEEDED(hr))
{
OutputDebugString(L"gesture type\n");
if (mtype == GestureType_Discrete)
{
OutputDebugString(L"discrete\n");
}
else if (mtype == GestureType_Continuous)
{
OutputDebugString(L"continuous\n");
}
}
else
{
OutputDebugString(L"no gesture type\n");
}
hr = m_pgesturelist[i]->get_Name(260, sName);
//gesture name
if (SUCCEEDED(hr))
{
OutputDebugString(L"gesture name\n");
StringCchPrintf(smessage, _countof(smessage), L"%s \t %d \n", sName, i);
OutputDebugString(smessage);
}
else
{
OutputDebugString(L"no name\n");
}
}
}
else
{
OutputDebugString(L"not received gestures\n");
}
for (int i = 0; i < BODY_COUNT; ++i)
{
//add gestures to the source
hr = m_pVGBFrameSource[i]->AddGestures(iGestureCount, m_pgesturelist);
if (SUCCEEDED(hr))
{
OutputDebugString(L"Gesture added\n");
}
else
{
OutputDebugString(L"not added\n");
}
}
}
//function to read the vgb frame and process if the gesture is detected
void CBodyBasics::ReadVGBFrameMultiple(int t_bodyCount)
{
HRESULT hr;
for (int i = 0; i < t_bodyCount; i++)
{
hr = m_pVGBFrameReader[i]->CalculateAndAcquireLatestFrame(&m_pVGBFrame);
if (SUCCEEDED(hr) && m_pVGBFrame != nullptr)
{
OutputDebugString(L"vgb frame\n");
BOOLEAN bGestureTracked = false;
hr = m_pVGBFrame->get_IsTrackingIdValid(&bGestureTracked);
if (SUCCEEDED(hr) && bGestureTracked)
{
OutputDebugString(L"valid gesture id and gesture tracked\n");
GestureType gesturetype;
m_pgesturelist[i]->get_GestureType(&gesturetype);
switch (gesturetype)
{
case GestureType::GestureType_Discrete:
hr = m_pVGBFrame->get_DiscreteGestureResult(m_pgesturelist[i], &m_pDiscreteResult);
if (SUCCEEDED(hr) && m_pDiscreteResult != nullptr)
{
OutputDebugString(L"discrete result\n");
BOOLEAN bDetected = false;
hr = m_pDiscreteResult->get_Detected(&bDetected);
if (SUCCEEDED(hr) && bDetected)
{
OutputDebugString(L"gesture detected\n");
StringCchPrintf(smessage, _countof(smessage), L"gesture detected %d\n", bDetected);
OutputDebugString(smessage);
float confidence = 0.0f;
hr = m_pDiscreteResult->get_Confidence(&confidence);
if (SUCCEEDED(hr) && confidence != 0.0f)
{
OutputDebugString(L"confidence is detected \t");
//if (confidence > 0.3f)
//{
StringCchPrintf(smessage, _countof(smessage), L"confidence value is %f\n", confidence);
OutputDebugString(smessage);
//}
}
else
{
OutputDebugString(L"no confidence\n");
}
}
else
{
OutputDebugString(L"gesture not detected\n");
}
}
else
{
OutputDebugString(L"no discrete result\n");
}
case GestureType::GestureType_Continuous:
hr = m_pVGBFrame->get_ContinuousGestureResult(m_pgesturelist[i], &m_pContinousResult);
if (SUCCEEDED(hr) && m_pContinousResult != nullptr)
{
OutputDebugString(L"continuous gesture\n");
WCHAR gesturename[100];
hr = m_pgesturelist[i]->get_Name(100, gesturename);
//if (gesturename == L"SwipeLeft")
//{
float progress = 0.0f;
OutputDebugString(L"get progress of continuous gesture \t");
hr = m_pContinousResult->get_Progress(&progress);
if (SUCCEEDED(hr) && progress != 0.0f)
{
StringCchPrintf(smessage, _countof(smessage), L"progress value is %f\n", progress);
OutputDebugString(smessage);
}
//}
}
else
{
OutputDebugString(L"no continuous gesture\n");
}
default:
break;
}
}
else
{
OutputDebugString(L"invalid gesture id\n");
}
}
else
{
OutputDebugString(L"no frame\n");
}
}
}
Is there wrong in my code? Do I need to modify my code? Can anyone help me?
As the picture shows,when in the long connection mode,the server recv and send,the client send and recv.And my question is:
Can I only just use the send in the client and just use the recv in the server?
The test code:
The server:
//#include "stdafx.h"
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
int main(int argc, char* argv[])
{
WORD sockVersion = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(sockVersion, &wsaData) != 0)
{
return 0;
}
SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (slisten == INVALID_SOCKET)
{
printf("socket error !");
return 0;
}
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(8888);
sin.sin_addr.S_un.S_addr = INADDR_ANY;//
if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
{
printf("bind error !");
}
if (listen(slisten, 30) == SOCKET_ERROR)
{
printf("listen error !");
return 0;
}
SOCKET sClient;
sockaddr_in remoteAddr;
int nAddrlen = sizeof(remoteAddr);
char revData[255];
while (true)
{
printf("waitting...\n");
sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen);
if (sClient == INVALID_SOCKET)
{
printf("accept error !");
continue;
}
printf("receive a connection:%s \r\n", inet_ntoa(remoteAddr.sin_addr));
char * sendData = "R\n";
//
while (1)
{
int ret = recv(sClient, revData, 255, 0);
if (ret > 0)
{
revData[ret] = 0x00;
printf(revData);
//new add code
//send(sClient, sendData, strlen(sendData), 0);
}
else
break;
}
closesocket(sClient);
}
closesocket(slisten);
WSACleanup();
return 0;
}
The client:
//#include "stdafx.h"
#include <WINSOCK2.H>
#include <STDIO.H>
#pragma comment(lib,"ws2_32.lib")
int main(int argc, char* argv[])
{
WORD sockVersion = MAKEWORD(2, 2);
WSADATA data;
if (WSAStartup(sockVersion, &data) != 0)
{
return 0;
}
SOCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sclient == INVALID_SOCKET)
{
printf("invalid socket !");
return 0;
}
sockaddr_in serAddr;
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(8888);
serAddr.sin_addr.S_un.S_addr = inet_addr("10.92.1.148");
if (connect(sclient, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
{
printf("connect error !");
closesocket(sclient);
return 0;
}
char * sendData = "T\n";
int cnt = 0;
char recData[255];
while (1)
{
send(sclient, sendData, strlen(sendData), 0);
//new add code
//int ret = recv(sclient, recData, 255, 0);
//if (ret > 0)
//{
// recData[ret] = 0x00;
// printf(recData);
//}
}
printf("cnt=%d\n",cnt);
closesocket(sclient);
WSACleanup();
return 0;
}
The code is wrong when I test.While when I add the new code,the program can run.The new code is the code after the // as the above .So I think just have send in one side and recv in another side maybe wrong.It have to have a loop.Is it right?Must I have a loop(request and response loop in the picture)?
I want to zero-out the contents of an UnsafeMutablePointer in Swift.
In C you usually have something like this:
void freeSecure(void *buffer, uint64_t size) {
// Create volatile pointer to make sure that the code won't be optimized away
volatile uint8_t *ptr = buffer;
for (uint64_t i = 0; i < size; i++) ptr[i] = 0x00;
free(buffer);
}
How can I achieve the same thing in Swift?
// Is extension of `UnsafeMutablePointer`
public func KC_dealloc(allocated: Int) {
if num == 0 {
self.destroy()
self.dealloc(allocated)
return
}
let byteCount = sizeof(Memory) * allocated
let ptr = UnsafeMutablePointer<UInt8>(self) // volatile???
for var i = 0; i < byteCount; i++ {
ptr[i] = 0x00
}
self.destroy()
self.dealloc(allocated)
}
Okay, I asked the same question in the Apple-developer-forum and some guy there pointed me to the memset_s-function which does what I want.
So my Swift-code should look like this:
// Is extension of `UnsafeMutablePointer`
public func KC_dealloc(allocated: Int) {
if num == 0 {
self.destroy()
self.dealloc(allocated)
return
}
let byteCount = sizeof(Memory) * allocated
let ptr = UnsafeMutablePointer<UInt8>(self) // volatile???
memset_s(ptr, byteCount, 0x00, byteCount) // Defined in C11
self.destroy()
self.dealloc(allocated)
}
I'm working to convert to Swift this code which helps get me get audio data for visualizations. The code I'm working with in Obj C, which works well, is:
while (reader.status == AVAssetReaderStatusReading) {
AVAssetReaderTrackOutput *trackOutput = (AVAssetReaderTrackOutput *)[reader.outputs objectAtIndex:0];
self.sampleBufferRef = [trackOutput copyNextSampleBuffer];
if (self.sampleBufferRef) {
CMBlockBufferRef blockBufferRef = CMSampleBufferGetDataBuffer(self.sampleBufferRef);
size_t bufferLength = CMBlockBufferGetDataLength(blockBufferRef);
void *data = malloc(bufferLength);
CMBlockBufferCopyDataBytes(blockBufferRef, 0, bufferLength, data);
SInt16 *samples = (SInt16 *)data;
int sampleCount = bufferLength / bytesPerInputSample;
for (int i=0; i<sampleCount; i+=100) {
Float32 sample = (Float32) *samples++;
sample = decibel(sample);
sample = minMaxX(sample,noiseFloor,0);
tally += sample;
for (int j=1; j<channelCount; j++)
samples++;
tallyCount++;
if (tallyCount == downsampleFactor) {
sample = tally / tallyCount;
maximum = maximum > sample ? maximum : sample;
[fullSongData appendBytes:&sample length:sizeof(sample)];//tried dividing the sample by 2
tally = 0;
tallyCount = 0;
outSamples++;
}
}
CMSampleBufferInvalidate(self.sampleBufferRef);
CFRelease(self.sampleBufferRef);
free(data);
}
}
In Swift, I'm trying to write is this part:
while (reader.status == AVAssetReaderStatus.Reading) {
var trackOutput = reader.outputs[0] as! AVAssetReaderTrackOutput
self.sampleBufferRef = trackOutput.copyNextSampleBuffer()
if (self.sampleBufferRef != nil) {
let blockBufferRef = CMSampleBufferGetDataBuffer(self.sampleBufferRef)
let bufferLength = CMBlockBufferGetDataLength(blockBufferRef)
var data = NSMutableData(length: bufferLength)
CMBlockBufferCopyDataBytes(blockBufferRef, 0, bufferLength, data!.mutableBytes)
var samples = UnsafeMutablePointer<Int16>(data!.mutableBytes)
var sampleCount = Int32(bufferLength)/bytesPerInputSample
for var i = 0; i < Int(sampleCount); i++ {
var sampleValue = CGFloat(samples[i]) etc. etc.
However, when I println() sampleValue is just comes out (Opaque Value) in the console. I can't figure out how to actually read the sampleValue.
I'm new at trying to read audio data for visualization purposes. Any help on getting a buffer of audio data to work with would be helpful. Thank you.
Use stride?
let bytesPerInputSample = 4 // assumption ;)
var samplePtr = data.mutableBytes
for _ in stride(from: 0, to: data.length, by: bytesPerInputSample) {
let currentSample = Data(bytes: samplePtr, count: bytesPerInputSample)
// do whatever is needed with current sample
//...
// increase ptr by size of sample
samplePtr = samplePtr + bytesPerInputSample
}
I code to send a touch event to my app by GSEvent,get mach_port_t by GSCopyPurpleSystemEventPort().
the sending function was launched after the ApplicationDidFinishLaunch:option have completed.the app is UIControlView app.
code as follow:
void handleMouseEventAtPoint(CGPoint point, int buttons)
{
// NOTE: Must store button state for comparision, port for
// mouse dragging and button up
static int buttons_;
static mach_port_t port_;
int diff = buttons_ ^ buttons;
bool twas = ((buttons_ & 0x1) != 0);
bool tis = ((buttons & 0x1) != 0);
buttons_ = buttons;
// Round point values to prevent subpixel coordinates
point.x = roundf(point.x);
point.y = roundf(point.y);
// Check for mouse button events
mach_port_t purple;
if ((diff & 0x10) != 0) {
// Simulate Headset button press
struct GSEventRecord record;
memset(&record, 0, sizeof(record));
record.type = (buttons & 0x4) != 0 ?
kGSEventHeadsetButtonDown :
kGSEventHeadsetButtonUp;
record.timestamp = GSCurrentEventTimestamp();
FixRecord(&record);
GSSendSystemEvent(&record);
}
if ((diff & buttonThree) != 0) {
// Simulate Home button press
struct GSEventRecord record;
memset(&record, 0, sizeof(record));
record.type = (buttons & buttonThree) != 0 ?
kGSEventMenuButtonDown :
kGSEventMenuButtonUp;
record.timestamp = GSCurrentEventTimestamp();
FixRecord(&record);
GSSendSystemEvent(&record);
}
if ((diff & buttonTwo) != 0)
{
// Simulate Sleep/Wake button press
struct GSEventRecord record;
memset(&record, 0, sizeof(record));
record.type = (buttons & buttonTwo) != 0 ?
kGSEventLockButtonDown :
kGSEventLockButtonUp;
record.timestamp = GSCurrentEventTimestamp();
FixRecord(&record);
GSSendSystemEvent(&record);
}
if (twas != tis || tis) {
// Main (left button) state changed, or was dragged
struct {
struct GSEventRecord record;
struct
{
struct GSEventRecordInfo info;
struct GSPathInfo path;
} data;
} event;
memset(&event, 0, sizeof(event));
event.record.type = kGSEventHand;
event.record.windowLocation = point;
event.record.timestamp = GSCurrentEventTimestamp();
event.record.infoSize = sizeof(event.data);
event.data.info.handInfo.type = twas == tis ?
kGSHandInfoTypeTouchDragged :
tis ?
kGSHandInfoTypeTouchDown :
kGSHandInfoTypeTouchUp;
event.data.info.handInfo._0x44 = 0x1;
event.data.info.handInfo._0x48 = tis ? 0x1 : 0x0;
event.data.info.pathPositions = 1;
event.data.path.pathIndex = 0x01;
event.data.path.pathIdentity = 0x02;
event.data.path.pathProximity = tis ? 0x03 : 0x00;
event.data.path.pathLocation = event.record.windowLocation;
if (twas != tis && tis)
{
// Button down and was not down before
port_ = 0;
CAWindowServer *server;
server = [CAWindowServer serverIfRunning];
char svrptrstr [255];
sprintf(svrptrstr, "%p", server);
NSLog(#"One!");
if (server = [CAWindowServer serverIfRunning])
//if (true)
{
NSLog(#"Two!");
//NSArray *displays([server displays]);
NSArray *displays = [server displays];
if (displays != nil && [displays count] != 0)
{
NSLog(#"Three!");
//CAWindowServer *display;
if (CAWindowServerDisplay *display = [displays objectAtIndex:0])
{
NSLog(#"Four!");
port_ = [display clientPortAtPosition:point];
}
}
}
if (port_ == 0)
{
// Is SpringBoard
if (purple == 0)
{
purple = GSGetPurpleSystemEventPort();
port_ = purple;
}
}
}
FixRecord(&event.record);
GSSendEvent(&event.record, port_);
NSLog(#"Event sent!");
//GSSendSystemEvent(&event.record);
//GSSendEvent(&event.record, purple);
}
if (purple != 0 && PurpleAllocated)
{
mach_port_deallocate(mach_task_self(), purple);
NSLog(#"Deallocated mach_port!");
}
}
but the app launch on the jailbreak ipad2(iOS5.01),there is no any click result,if click event was done,the debug.log would be there.
who can tell me what i have miss?
I've seen this code somewhere else (I think it was on an app that translated mouse clicks to iPhone/iPad taps). The problem here is not the code or the port, but the event structure you are sending. This is the GSevent structure for iOS 3.0, not for iOS 5.0. It has changed, not only in structure but in values and tags. I suggest receiving UIEvents, translating them into GSEvents and looking at their content.