Linphone fails to create SAS for ZRTP Secure call - security

I have recently updated my Linphone library from latest release to follow Appleā€™s IPV6 standard support.
But it fails to create secure call.
Each time i try to convert call to secure call ,Acknowledgment fails and SAS returns null.
Same thing working with old library(IPV4 Support).
I am using ZRTP Encryption for Secure call.
I am struggling with since last 15 days.
Below line of code returns SAS value null.
NSString *localLize = NSLocalizedString(#"Confirm the following SAS with peer:\n%s", nil);
const char *authToken = linphone_call_get_authentication_token(call);
NSLog(#"localize %# authToken %s",localLize,authToken);
Below is full function to convert call to security call.
- (IBAction)onSecurityClick:(id)sender {
if (linphone_core_get_calls_nb(LC)) {
LinphoneCall *call = linphone_core_get_current_call(LC);
if (call != NULL) {
//force encryption ZRTP
LinphoneMediaEncryption enc = LinphoneMediaEncryptionZRTP;
if (enc == LinphoneMediaEncryptionZRTP) {
NSString *localLize = NSLocalizedString(#"Confirm the following SAS with peer:\n%s", nil);
const char *authToken = linphone_call_get_authentication_token(call);
NSLog(#"localize %# authToken %s",localLize,authToken);
NSString *message =
[NSString stringWithFormat:NSLocalizedString(#"Confirm the following SAS with peer:\n%s", nil),
linphone_call_get_authentication_token(call)];
if (securityDialog == nil) {
__block __strong StatusBarView *weakSelf = self;
securityDialog = [UIConfirmationDialog ShowWithMessage:message
cancelMessage:NSLocalizedString(#"DENY", nil)
confirmMessage:NSLocalizedString(#"ACCEPT", nil)
onCancelClick:^() {
if (linphone_core_get_current_call(LC) == call) {
linphone_call_set_authentication_token_verified(call, NO);
}
weakSelf->securityDialog = nil;
}
onConfirmationClick:^() {
if (linphone_core_get_current_call(LC) == call) {
linphone_call_set_authentication_token_verified(call, YES);
}
weakSelf->securityDialog = nil;
}];
}
}
}
}
}
Any help should be appreciable.
Thanks in Advance.

So I figured out what was the problem for me. Maybe can be useful for you too.
I was calling linphone_call_get_authentication_token immediately after the call state changed to LinphoneCallOutgoingProgress. All I had to do to fix it was to start a Timer that calls a method every 1 second when the call state changes to LinphoneCallOutgoingProgress because it takes some time for the SAS to be generated it seems. Here's what worked for me:
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) {
DispatchQueue.main.async {
let sas = linphone_call_get_authentication_token(Call.current())
if sas != nil {
self!.sasLabel.text = String(cString: sas!)
timer.invalidate()
}
}
}

Related

Programmatically Change data in a core data file

Hello All & Thanks in Advance!
I am a noob with Core Data and I need to change data in one of my fields which is named: recid.
I have created a index which again is: recid as int 16 in my core data model.
What I am needing to do is fetch the record and changed recid from we will say 5 to 1 how would I go about doing this?
Here is the code I have built so far & I will take care of my loop after I understand how to change the data in the record.
-(void)awakeFromNib
{
NSMenu *theMenu;
statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength] retain];
[statusItem setMenu:statusMenu];
[statusItem setImage:[NSImage imageNamed:#"TheJournal_16x16x32"]];
[statusItem setHighlightMode:YES];
theMenu = [[NSMenu alloc] initWithTitle:#""];
[theMenu addItemWithTitle:#"The Journal" action:#selector(showTheWindow:) keyEquivalent:#"W"];
[theMenu addItemWithTitle:#"Quit" action:#selector(terminate:) keyEquivalent:#"Q"];
[statusItem setMenu:theMenu];
[theMenu release];
NSUInteger count;
count = 0;
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
count = [prefs integerForKey:#"recid"];
NSLog(#"counter is >>>>%lu",(unsigned long)count);
[prefs setInteger:count forKey:#"recid"];
count++;
NSUserDefaults *prefs1 = [NSUserDefaults standardUserDefaults];
[prefs1 setInteger:count forKey:#"recid"];
NSLog(#"counter is >>>>%lu",(unsigned long)count);
// How I fetch the record & change the value from 5 to 1?
}
Here's a code sample that may help you. In this example, the YourManagedClass Core Data entity uses a UUID string as a unique record identifier. The extension contains a static function that fetches the unique record, sets the new recid value and then saves the NSManagedObjectContext.
import Foundation
import CoreData
class YourManagedClass: NSManagedObject {
#NSManaged var uuid: String?
#NSManaged var recid: NSNumber?
}
extension YourManagedClass {
static func set(recID: Int16, forObject uuid: String, `in` context: NSManagedObjectContext) {
let fetchRequest = NSFetchRequest<YourManagedClass>(entityName: "YourManagedClass")
fetchRequest.predicate = NSPredicate(format: "uuid = %#", argumentArray: [uuid])
let object: YourManagedClass
do {
let objects = try context.fetch(fetchRequest)
guard let foundObject = objects.first else {
return
}
object = foundObject
} catch {
// Handle Error
return
}
object.recid = NSNumber(value: recID)
do {
try context.save()
} catch {
// Handle Error
}
}
}
You would then call this function with a reference to your NSManagedObjectContext ('context' here):
YourManagedClass.set(recID: 15, forObject: "909455F3-C812-4399-83B4-F96A5C32A71D", in: context)

device.GattServices returns an empty set for BLE devices on a Windows universal app

I am using the sample from Microsoft. When an advertisement is received I am calling
BluetoothLEDevice device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
and then
device.GattServices()
but that always returns an empty list. Why is this happening? I have found no answer whatsoever.
If you want this to work by using advertisement watcher, you need to target the windows 10 creators update(10.0;Build 15063) and use the latest SDK, otherwise you will have to pair the device first.
To get the GattServices, first check if the device is not null.
Then use:
var serviceResult = await bluetoothLeDevice.GetGattServicesAsync();
if (serviceResult.Status == GattCommunicationStatus.Success)
{
//Do something with servivicResult list
}
But there is a catch; It can be that serviceResult.Status returns success, but not all or no services have been found yet.
My solution is to put it in a loop with a short delay and try it a few times until serviceResult count stays the same.
I wanted to put more explanation in my comment, but something went wrong and cannot edit my comment so I will add it as an answer.
I had exactly the same problem. for some reason you have to initialize your BLEdevice as null.
private BluetoothLEDevice device = null;
Also to prevent that you advertisementWatcher is setting your device over and over, use an if statement to set it only when the divice is null,
if (device == null)
{
device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
}
or if you want to set multiple devices than add them to a collection and make sure each device is only added once.
This is my working code :
private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher,
BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
BluetoothLEAdvertisementType advertisementType = eventArgs.AdvertisementType;
short rssi = eventArgs.RawSignalStrengthInDBm;
string localName = eventArgs.Advertisement.LocalName;
string manufacturerDataString = "";
var manufacturerSections = eventArgs.Advertisement.ManufacturerData;
if (manufacturerSections.Count > 0)
{
// Only print the first one of the list
var manufacturerData = manufacturerSections[0];
var data = new byte[manufacturerData.Data.Length];
using (var reader = DataReader.FromBuffer(manufacturerData.Data))
{
reader.ReadBytes(data);
}
manufacturerDataString = string.Format("0x{0}: {1}",
manufacturerData.CompanyId.ToString("X"),
BitConverter.ToString(data));
}
string res = string.Format("type={0}, rssi={1}, name={2}, manufacturerData=[{3}]",
advertisementType.ToString(),
rssi.ToString(),
localName,
manufacturerDataString);
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
textBoxWatcher.Text = res;
});
if (device == null)
{
device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
if (device != null)
{
var deviceInfo = device.DeviceInformation;
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
if (device.Name != string.Empty)
{
//ResultCollection is a observable observable collection of blueutooth devices
// to bind to a listvieuw,it is not needed!
ResultCollection.Add(new BleDevice(device));
if (deviceInfo.Name == "HMSoft")
{
if (ResultCollection[0] is BleDevice bleDevice)
{
BleDeviceId = bleDevice.Id;
SelectedBleDeviceName = bleDevice.Name;
}
Connect();
}
}
});
}
}

How do I call CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer?

I'm trying to figure out how to call this AVFoundation function in Swift. I've spent a ton of time fiddling with declarations and syntax, and got this far. The compiler is mostly happy, but I'm left with one last quandary.
public func captureOutput(
captureOutput: AVCaptureOutput!,
didOutputSampleBuffer sampleBuffer: CMSampleBuffer!,
fromConnection connection: AVCaptureConnection!
) {
let samplesInBuffer = CMSampleBufferGetNumSamples(sampleBuffer)
var audioBufferList: AudioBufferList
var buffer: Unmanaged<CMBlockBuffer>? = nil
CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(
sampleBuffer,
nil,
&audioBufferList,
UInt(sizeof(audioBufferList.dynamicType)),
nil,
nil,
UInt32(kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment),
&buffer
)
// do stuff
}
The compiler complains for the 3rd and 4th arguments:
Address of variable 'audioBufferList' taken before it is initialized
and
Variable 'audioBufferList' used before being initialized
So what am I supposed to do here?
I'm working off of this StackOverflow answer but it's Objective-C. I'm trying to translate it into Swift, but run into this problem.
Or is there possibly a better approach? I need to read the data from the buffer, one sample at a time, so I'm basically trying to get an array of the samples that I can iterate over.
Disclaimer: I have just tried to translate the code from Reading audio samples via AVAssetReader to Swift, and verified that it compiles. I have not
tested if it really works.
// Needs to be initialized somehow, even if we take only the address
var audioBufferList = AudioBufferList(mNumberBuffers: 1,
mBuffers: AudioBuffer(mNumberChannels: 0, mDataByteSize: 0, mData: nil))
var buffer: Unmanaged<CMBlockBuffer>? = nil
CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(
sampleBuffer,
nil,
&audioBufferList,
UInt(sizeof(audioBufferList.dynamicType)),
nil,
nil,
UInt32(kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment),
&buffer
)
// Ensure that the buffer is released automatically.
let buf = buffer!.takeRetainedValue()
// Create UnsafeBufferPointer from the variable length array starting at audioBufferList.mBuffers
let audioBuffers = UnsafeBufferPointer<AudioBuffer>(start: &audioBufferList.mBuffers,
count: Int(audioBufferList.mNumberBuffers))
for audioBuffer in audioBuffers {
// Create UnsafeBufferPointer<Int16> from the buffer data pointer
var samples = UnsafeMutableBufferPointer<Int16>(start: UnsafeMutablePointer(audioBuffer.mData),
count: Int(audioBuffer.mDataByteSize)/sizeof(Int16))
for sample in samples {
// ....
}
}
Swift3 solution:
func loopAmplitudes(audioFileUrl: URL) {
let asset = AVAsset(url: audioFileUrl)
let reader = try! AVAssetReader(asset: asset)
let track = asset.tracks(withMediaType: AVMediaTypeAudio)[0]
let settings = [
AVFormatIDKey : kAudioFormatLinearPCM
]
let readerOutput = AVAssetReaderTrackOutput(track: track, outputSettings: settings)
reader.add(readerOutput)
reader.startReading()
while let buffer = readerOutput.copyNextSampleBuffer() {
var audioBufferList = AudioBufferList(mNumberBuffers: 1, mBuffers: AudioBuffer(mNumberChannels: 0, mDataByteSize: 0, mData: nil))
var blockBuffer: CMBlockBuffer?
CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(
buffer,
nil,
&audioBufferList,
MemoryLayout<AudioBufferList>.size,
nil,
nil,
kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment,
&blockBuffer
);
let buffers = UnsafeBufferPointer<AudioBuffer>(start: &audioBufferList.mBuffers, count: Int(audioBufferList.mNumberBuffers))
for buffer in buffers {
let samplesCount = Int(buffer.mDataByteSize) / MemoryLayout<Int16>.size
let samplesPointer = audioBufferList.mBuffers.mData!.bindMemory(to: Int16.self, capacity: samplesCount)
let samples = UnsafeMutableBufferPointer<Int16>(start: samplesPointer, count: samplesCount)
for sample in samples {
//do something with you sample (which is Int16 amplitude value)
}
}
}
}
The answers posted here make assumptions about the size of the necessary AudioBufferList -- which may have allowed them to have work in their particular circumstance, but didn't work for me when receiving audio from a AVCaptureSession. (Apple's own sample code didn't work either.)
The documentation on CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer is not obvious, but it turns out you can ask the function it how big AudioListBuffer item should be first, and then call it a second time with an AudioBufferList allocated to the size it wants.
Below is a C++ example (sorry, don't know Swift) that shows a more general solution that worked for me.
// ask the function how big the audio buffer list should be for this
// sample buffer ref
size_t requiredABLSize = 0;
err = CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer,
&requiredABLSize,
NULL,
NULL,
kCFAllocatorSystemDefault,
kCFAllocatorSystemDefault,
kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment,
NULL);
// allocate an audio buffer list of the required size
AudioBufferList* audioBufferList = (AudioBufferList*) malloc(requiredABLSize);
// ensure that blockBuffer is NULL in case the function fails
CMBlockBufferRef blockBuffer = NULL;
// now let the function allocate fill in the ABL for you
err = CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer,
NULL,
audioBufferList,
requiredABLSize,
kCFAllocatorSystemDefault,
kCFAllocatorSystemDefault,
kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment,
&blockBuffer);
// if we succeeded...
if (err == noErr) {
// la la la... read your samples...
}
// release the allocated block buffer
if (blockBuffer != NULL) {
CFRelease(blockBuffer);
blockBuffer = NULL;
}
// release the allocated ABL
if (audioBufferList != NULL) {
free(audioBufferList);
audioBufferList = NULL;
}
I'll leave it up to the Swift experts to offer an implementation in that language.
Martin's answer works and does exactly what I asked in the question, however, after posting the question and spending more time with the problem (and before seeing Martin's answer), I came up with this:
public func captureOutput(
captureOutput: AVCaptureOutput!,
didOutputSampleBuffer sampleBuffer: CMSampleBuffer!,
fromConnection connection: AVCaptureConnection!
) {
let samplesInBuffer = CMSampleBufferGetNumSamples(sampleBuffer)
self.currentZ = Double(samplesInBuffer)
let buffer: CMBlockBufferRef = CMSampleBufferGetDataBuffer(sampleBuffer)
var lengthAtOffset: size_t = 0
var totalLength: size_t = 0
var data: UnsafeMutablePointer<Int8> = nil
if( CMBlockBufferGetDataPointer( buffer, 0, &lengthAtOffset, &totalLength, &data ) != noErr ) {
println("some sort of error happened")
} else {
for i in stride(from: 0, to: totalLength, by: 2) {
// do stuff
}
}
}
This is a slightly different approach, and probably still has room for improvement, but the main point here is that at least on an iPad Mini (and probably other devices), each time this method is called, we get 1,024 samples. But those samples come in an array of 2,048 Int8 values. Every other one is the left/right byte that needs to be combined into to make an Int16 to turn the 2,048 half-samples into 1,024 whole samples.
it works for me. try it:
let musicUrl: NSURL = mediaItemCollection.items[0].valueForProperty(MPMediaItemPropertyAssetURL) as! NSURL
let asset: AVURLAsset = AVURLAsset(URL: musicUrl, options: nil)
let assetOutput = AVAssetReaderTrackOutput(track: asset.tracks[0] as! AVAssetTrack, outputSettings: nil)
var error : NSError?
let assetReader: AVAssetReader = AVAssetReader(asset: asset, error: &error)
if error != nil {
print("Error asset Reader: \(error?.localizedDescription)")
}
assetReader.addOutput(assetOutput)
assetReader.startReading()
let sampleBuffer: CMSampleBufferRef = assetOutput.copyNextSampleBuffer()
var audioBufferList = AudioBufferList(mNumberBuffers: 1, mBuffers: AudioBuffer(mNumberChannels: 0, mDataByteSize: 0, mData: nil))
var blockBuffer: Unmanaged<CMBlockBuffer>? = nil
CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(
sampleBuffer,
nil,
&audioBufferList,
sizeof(audioBufferList.dynamicType), // instead of UInt(sizeof(audioBufferList.dynamicType))
nil,
nil,
UInt32(kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment),
&blockBuffer
)
I do this (swift 4.2):
let n = CMSampleBufferGetNumSamples(audioBuffer)
let format = CMSampleBufferGetFormatDescription(audioBuffer)!
let asbd = CMAudioFormatDescriptionGetStreamBasicDescription(format)!.pointee
let nChannels = Int(asbd.mChannelsPerFrame) // probably 2
let bufferlistSize = AudioBufferList.sizeInBytes(maximumBuffers: nChannels)
let abl = AudioBufferList.allocate(maximumBuffers: nChannels)
for i in 0..<nChannels {
abl[i] = AudioBuffer(mNumberChannels: 0, mDataByteSize: 0, mData: nil)
}
var block: CMBlockBuffer?
var status = CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(audioBuffer, bufferListSizeNeededOut: nil, bufferListOut: abl.unsafeMutablePointer, bufferListSize: bufferlistSize, blockBufferAllocator: nil, blockBufferMemoryAllocator: nil, flags: 0, blockBufferOut: &block)
assert(noErr == status)
// use AudioBufferList here (abl.unsafePointer), e.g. with ExtAudioFileWrite or what have you

Rename a snapshot in Hyper-V WMI V2 from C#

I am trying to rename a Hyper-V snapshot (checkpoint) using root\virtualization\v2. None of the standard methods like ModifySystemSettings or ModifyVirtualSystem of Msvm_VirtualSystemSnapshotService or Msvm_VirtualSystemManagementService has been helpful so far.
Powershell Rename-VMSnapshot can do the job however I am not sure it is using WMI.
Any idea?
Here is what worked for me:
//
// Rename last snapshot to desired name
//
using (ManagementBaseObject inParams = vmms.GetMethodParameters("ModifySystemSettings"))
{
ManagementObject setting = null;
ManagementObjectCollection settings = vm.GetRelated(
"Msvm_VirtualSystemSettingData",
"Msvm_MostCurrentSnapshotInBranch",
null,
null,
"Dependent",
"Antecedent",
false,
null
);
foreach (ManagementObject instance in settings)
{
// Usually only one, but loop through to the end to get latest one
if (setting != null)
{
if (string.Compare(
(string)instance["CreationTime"],
(string)setting["CreationTime"],
true) > 0
)
{
// Get latest one since there could be duplicates
setting = instance;
}
}
else
{
setting = instance;
}
}
setting["ElementName"] = snapshotName;
inParams["SystemSettings"] = setting.GetText(TextFormat.WmiDtd20);
using (ManagementBaseObject outParams = vmms.InvokeMethod("ModifySystemSettings", inParams, null))
{
// What this does is get Job managementObject and check JobState to be JobCompleted.
this.ProcessSnapshotMethodResult(outParams, "rename");
}
}

How to generate random bytes via Cryptographic Service Provider (CSP) without .NET/COM?

Is there a way to generate strong random bytes via Microsoft's Cryptographic Service Provider (CSP) without using .NET/COM? For example, using command line or some other way?
I'd like to use it in NodeJS to be more specific.
Refer to http://technet.microsoft.com/en-us/library/cc733055(v=ws.10).aspx
netsh nap client set csp name = <name> keylength = <keylength>
If this command works for you, just exec it through nodejs. (require('child_process').exec)
Yes, using the Windows API. Here is a sample C++ code:
#include "Wincrypt.h"
// ==========================================================================
HCRYPTPROV hCryptProv= NULL; // handle for a cryptographic provider context
// ==========================================================================
void DoneCrypt()
{
::CryptReleaseContext(hCryptProv, 0);
hCryptProv= NULL;
}
// --------------------------------------------------------------------------
// acquire crypto context and a key ccontainer
bool InitCrypt()
{
if (hCryptProv) // already initialized
return true;
if (::CryptAcquireContext(&hCryptProv , // handle to the CSP
NULL , // container name
NULL , // use the default provider
PROV_RSA_FULL , // provider type
CRYPT_VERIFYCONTEXT )) // flag values
{
atexit(DoneCrypt);
return true;
}
REPORT(REP_ERROR, _T("CryptAcquireContext failed"));
return false;
}
// --------------------------------------------------------------------------
// fill buffer with random data
bool RandomBuf(BYTE* pBuf, size_t nLen)
{
if (!hCryptProv)
if (!InitCrypt())
return false;
size_t nIndex= 0;
while (nLen-nIndex)
{
DWORD nCount= (nLen-nIndex > (DWORD)-1) ? (DWORD)-1 : (DWORD)(nLen-nIndex);
if (!::CryptGenRandom(hCryptProv, nCount, &pBuf[nIndex]))
{
REPORT(REP_ERROR, _T("CryptGenRandom failed"));
return false;
}
nIndex+= nCount;
}
return true;
}

Resources