CFStreamCreatePairWithSocketToHost get local endpoint address - ios

I'm new to iOS/MacOS programming and have not found any examples I understand. I imagine it is only a few lines of code to do this, so sorry if this is covered already but for the life of me I cannot find it.
I'm using CFStreamCreatePairWithSocketToHost to create in/out streams. I just want to get the local endpoint info (specifically the IP address, don't care about port really). I already obtain the public IP info from my server, but for security/logging reasons I need the local address as well.
This is on iOS, not MacOS, if it matters.

The following code demonstrates how to get the local socket address. It works with IPv4 and IPv6 addresses. (It is more than a few lines, perhaps somebody knows a shorter solution.)
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
// Create socket pair:
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStringRef remoteHost = CFSTR("localhost");
CFStreamCreatePairWithSocketToHost(NULL, remoteHost, 5555, &readStream, &writeStream);
// Write something (the socket is not valid before you read or write):
CFWriteStreamOpen(writeStream);
CFWriteStreamWrite(writeStream, "Hello\n", 6);
// Get the native socket handle:
CFDataRef socketData = CFWriteStreamCopyProperty(writeStream, kCFStreamPropertySocketNativeHandle);
CFSocketNativeHandle socket;
CFDataGetBytes(socketData, CFRangeMake(0, sizeof(CFSocketNativeHandle)), (UInt8 *)&socket);
// Get the local socket address from the socket handle:
struct sockaddr_storage sa;
socklen_t salen = sizeof(sa);
getsockname(socket, (struct sockaddr *)&sa, &salen);
// Get numeric host and port from socket address:
char host[NI_MAXHOST];
char service[NI_MAXSERV];
getnameinfo((struct sockaddr *)&sa, salen, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST|NI_NUMERICSERV);
NSLog(#"local address: %s, local port: %s", host, service);

Related

Sending an array to the IP core through SDK

I want to send an array to the IP design through SDK rather than just a number as shown in the following code snippet. Can somebody help me in doing that?
code in SDK
let's start saying that there are different way to send data to IP (for example from an ARM processor to a custom IP in a Zynq). Xilinx gives you the possibility to communicate using:
AXI4 FULL interface
AXI4 LITE interface
AXI4 STREAM interface
Depending on the interface you use, the way to write the SDK-code running on the ARM may be quite different. There are a lot of details but in general when you create an IP, after exporting the hardware and lunching the SDK, Vivado creates library and drivers for you in order to send data and commands to the every specific IP. Just to give you an example let's say that you are using the AXI STREAM interface. Here you should add another IP (provided from Xilinx) that manage the data transfer from memory to the IP and vice versa (DMA - direct memory access). Here the code should be :
#include <stdio.h>
#include "xil_cache.h"
#include "xaxidma.h"
#include "xparameters.h"
#include "math.h"
#include "xtime_l.h"
XTime tstart,tstop;
//#define DEBUG
#define N_samples 64
int main()
{
printf("Hello\n");
Xil_DCacheDisable();
Xil_ICacheDisable();
/***************** Variables *******************/
float input_R_IM[N_samples*2];
float output_R_IM[N_samples*2];
int error=-1;
XAxiDma dma0_pointer;
XAxiDma_Config *dma0_Config;
/**********************DMA initialization***************************/
dma0_Config=XAxiDma_LookupConfig(XPAR_AXIDMA_0_DEVICE_ID);
error=XAxiDma_CfgInitialize(&dma0_pointer,dma0_Config);
#ifdef DEBUG
if(error==XST_SUCCESS)
printf("...initialization successful\n");
else
printf("**ERROR INITIALIZATION\n");
#endif
float d = 2 * (float)M_PI / N_samples;
size_t i=NULL;
for (i = 0; i < N_samples; i++)
{
input_R_IM[i*2]=sin(0 + d*i);
input_R_IM[i*2+1]=0;
}
/**********************STARTING FFT************************/
error=-1;
XTime_GetTime(&tstart);
error = XAxiDma_SimpleTransfer(&dma0_pointer,(u32)input_R_IM,2*N_samples*sizeof(float),XAXIDMA_DMA_TO_DEVICE);
#ifdef DEBUG
if(error==XST_SUCCESS)
printf("...simply transfer 1 successful\n");
else
printf("**ERROR SIMPLY TRANSFER 1\n");
#endif
/***********************COPY BACK THE RESULTS************************/
// error=-1;
error = XAxiDma_SimpleTransfer(&dma0_pointer,(u32)output_R_IM,2*N_samples*sizeof(float),XAXIDMA_DEVICE_TO_DMA);
#ifdef DEBUG
if(error==XST_SUCCESS)
printf("...simply transfer 2 successful\n");
else
printf("**ERROR SIMPLY TRANSFER 2\n");
#endif
XTime_GetTime(&tstop);
u64 cycles = tstop-tstart;
float t = ((float)cycles / COUNTS_PER_SECOND)*1000000;
printf("cycles= %lld (time = %f us)\n",cycles,t);
for (i = 0; i < N_samples; i++)
{
printf("i: %d real=> %f --imag==> %f \n" ,i, output_R_IM[i*2], output_R_IM[i*2+1]);
}
printf("Goodbye\n");
return 0;
}
This is an old code used to send data from one of the ARM processor to the FFT IP using and AXI-DMA.
Here you can find an AXI reference Guide in order to have a better idea on how to manage the data between IP on Xilinx FPGA

libssh2 lib with ipv6 not working

In my iOS application I am using libssh2 library. I am trying to ssh with ipv6 address, But socket is not creating and getting nil socket. It's working fine with ipv4 address.
static CFSocketRef _CreateSocketConnectedToHost(NSString* name, UInt16 port, CFOptionFlags callBackTypes, CFSocketCallBack callback, const CFSocketContext* context, CFTimeInterval timeOut)
I have search for this but not finding any result for ipv6 support with libssh2.
Please help me, Is libssh2 not supporting for ipv6? Can we make it working using libssh2?
just need to use ipv6 property in socket instead of ipv4 and you able to create socket with ipv6 address.
struct sockaddr_in6 ipAddress6;
CFSocketSignature signature;
ipAddress6.sin6_port = htons(port);
signature.protocolFamily = AF_INET6;
signature.protocol = IPPROTO_IP;//IPPROTO_IPV6;
signature.address = (CFDataRef)[NSData dataWithBytes:&ipAddress6 length:ipAddress6.sin6_len];

Does CFHostGetAddressing() support ipv6 DNS entries?

I am trying to use CFHostGetAddressing to do a simple DNS lookup. However, I notice that it returns an array of sockaddr structs, which I guess means it can only do IPV4.
Is there a way to support DNS entries with IPV6 addresses in iOS? Perhaps a similar API that returns an array of sockaddr_storage structs?
The CFHostGetAddressing() documentation might be misleading, because struct sockaddr
is a structure that covers all the common elements of the various socket addresses (IPv4, IPv6, ...). It is usually only used to pass a generic pointer to the socket functions.
Actually CFHostGetAddressing() works well with IPv6. It returns an array of CFData elements where each element contains a struct sockaddr_in or a struct sockaddr_in6.
Using the code from your previous question as a starting point, the following should work:
let hostRef = CFHostCreateWithName(kCFAllocatorDefault, "localhost").takeRetainedValue()
var resolved = CFHostStartInfoResolution(hostRef, CFHostInfoType.Addresses, nil)
let addresses = CFHostGetAddressing(hostRef, &resolved).takeRetainedValue() as NSArray
for addr in addresses as [NSData] {
var sockaddr = UnsafePointer<sockaddr_storage>.alloc(1)
addr.getBytes(sockaddr, length: sizeof(sockaddr_storage))
// ...
sockaddr.destroy()
}

Stream from iOS to Server

How would I go about sending a live audio stream to a server? I currently can access raw PCM data as soon as it is being played from the iPhone speaker and want to allow others to grab it and stream it from a URL. Sort of like when you access an IceCast stream URL and it starts grabbing the stream.
I would like to clarify I am streaming from an iOS device to my server, so that if I were to type in a URL to my server it would start downloading where ever that stream on the phone is at and if the iDevice wasn't streaming then there would be nothing.
See Apple's documentation on output streams here
Note on iOS that you must set up an NSOutputStream as a CFStream (then cast via toll-free bridging) like so:
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)[website host], 80, &readStream, &writeStream);
NSInputStream *inputStream = (__bridge_transfer NSInputStream *)readStream;
NSOutputStream *outputStream = (__bridge_transfer NSOutputStream *)writeStream;
Other than that, the documentation gives you all the necessary information–keep in mind that PCM is very high bitrate, so there might be stream stuttering.
I'm not sure which framework you're using for microphone access, but when the delegate function is called indicating that a buffer is ready, just immediately write the contents of the buffer to the stream (example in the - (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode function).

CFStreamCreatePairWithSocketToCFHost CFStreamCreatePairWithSocketToHost and allocations

Can some one please give me the difference between CFStreamCreatePairWithSocketToCFHost and CFStreamCreatePairWithSocketToHost calls.
Also what is a CFAllocator and what is the meaning if that is NULL or kCFAllocatorDefault. Since its a kCFAllocatorDefault is a const can someone explain the beleifits of kCFAllocatorDefault or is it the for historical purposes only?
The difference between CFStreamCreatePairWithSocketToCFHost and CFStreamCreatePairWithSocketToHost is simply the way the address is passed in.
In CFStreamCreatePairWithSocketToHost, you can simply define a CFStringRef (or NSString) to represent the domain / ip of the host.
With the CFHost version, however, it gives you control over the address via the sockaddr_in struct, defined in <netinet/in.h>. You create a CFHostRef in a manner similar to the following:
struct sockaddr_in ip4addr; // note that this only works for ipv4, for ipv6 you need struct sockaddr_in6.
ip4addr.sin_family = AF_INET;
ip4addr.sin_port = htons(3490);
inet_pton(AF_INET, "10.0.0.1", &ip4addr.sin_addr);
CFDataRef sockData = CFDataCreate(NULL, &ip4addr, sizeof(ip4addr));
CFHostRef host = CFHostCreateWithAddress(NULL, sockData);
// use 'host' to create your stream
CFRelease(host);
CFRelease(sockData);
This gives you some (mostly unnecessary) control over what you do with the socket itself, for most situations, the CFHost version is not necessary.
For CFAllocator's, once again, the documentation is your friend. It is used as CoreFoundation's way for debugging malloc, free, and realloc calls throughout the code.
It is an object that allows you to write your own methods for allocating memory for an object, and kCFAllocatorDefault uses the standard malloc, free, and realloc calls used by the system. Passing NULL for a CFAllocator works exactly the same as kCFAllocatorDefault, the code just uses the system calls.

Resources