I want to be able to explicitly set the TTL value for a socket connection using Cocoa. I've been unable to see anything useful in the CoreFoundation docs. Do I need to go even lower to the BSD Sockets to set the TTL value?
Are you writing YA variant of traceroute? ;)
And yes, plain C sockets API is your friend: call as usual setsockopt() with IP_TTL socket option for IPv4 or IPV6_UNICAST_HOPS for IPv6.
There are two possibilities.
1) You can use plain C/Unix style sockets, so that you first create your socket, then set its options using setsockopt() including the ones you want to add (you may want to check first if these are supported), and finally you create a a CFSocket using CFSocketCreateWithNative().
2) You use directly the CF Apis, for instance
CFSocketSendData
Sends data over a CFSocket object.
CFSocketError CFSocketSendData (
CFSocketRef s,
CFDataRef address,
CFDataRef data,
CFTimeInterval timeout
);
allows you to set a timeout, which is equivalent to setting the socket option SO_SNDTIMEO.
CFSocketCreateConnectedToSocketSignature
Creates a CFSocket object and opens a connection to a remote socket.
CFSocketRef CFSocketCreateConnectedToSocketSignature (
CFAllocatorRef allocator,
const CFSocketSignature *signature,
CFOptionFlags callBackTypes,
CFSocketCallBack callout,
const CFSocketContext *context,
CFTimeInterval timeout
);
Kind regards.
I used CocoaAsyncSocket library. It contains a class called AsyncUdpSocket which is an Obj-C wrapper around the lower-level socket API. I added a method to set TTL of a socket.
-(BOOL)setTTL:(int) ttlValue {
int socketFD = SOCKET_NULL;
if ( socket4FD != SOCKET_NULL) {
socketFD = socket4FD;
}
else{
if ( socket6FD != SOCKET_NULL) {
socketFD = socket6FD;
}
else{
NSLog(#"ERROR: TTL - No Socket Found!");
return NO;
}
}
int status = setsockopt(socketFD, IPPROTO_IP, IP_TTL, &ttlValue, sizeof(ttlValue));
if (status == -1){
NSLog(#"Error: TTL not set!");
return NO;
}
NSLog(#"TTL: %d", ttlValue);
return YES;
}
I only tested it for IPv4. For IPv6 try with IPv6_UNICAST_HOPS
Related
I have a netfilter module which hooks into NF_INET_LOCAL_OUT. In the hook function, I set the mark as follows:
if (tcp_header->syn && dport == 80) {
skb->mark = 0x1;
}
However, this seems to set the mark only for this packet and not the connection mark.
How do I set the connmark to 0x1 so that all packets in this flow
have this mark?
How do I access connmark for a packet in the
hook function?
Thanks for your help.
NB: I am not a kernel network guru; I'm just good at reading the network code itself :)
Cribbing entirely from net/netfilter/xt_connmark.c in the latest version (4.15.8), try the following code:
if (tcp_header->syn && dport == 80) {
skb->mark = 0x1;
enum ip_conntrack_info ctinfo;
struct nf_conn *ct;
ct = nf_ct_get(skb, &ctinfo);
if (ct != NULL) {
u_int32_t newmark;
newmark = 0x01;
if (ct->mark != newmark) {
ct->mark = newmark;
nf_conntrack_event_cache(IPCT_MARK, ct);
}
}
}
Basically, in order to set the CONNMARK itself, you need to first get the actual conntrack entry for the flow. Once you've done that, you see if the current mark is already set to your new mark of 0x01. If it isn't, you set the mark and fire an event that the mark has been set.
You may want to look a bit more into connmark_tg, which is where this snippet is modified from; it may give you a bit more insight than just this code block alone.
Best of luck!
I need to pass data between CoreAudio's realtime thread and the UI thread (one way, RT->UI). I know I can't use any Cocoa/Objective C methods like performSelectorOnMainThread or NSNotification and I can't use anything that will allocate memory as this will potentially block the RT thread.
What is the correct method for communicating between threads? Can I use GCD message queues or is there a more basic system to use?
Edit:
Thinking about this a bit more, I suppose I could use a lock free ring buffer, which the RT thread puts a message into, and the UI thread checks for messages to pull out. Is this the best way and if so is there a system already to do this in CoreAudio or available elsewhere or do I need to code it up myself?
It turns out this was a lot simpler than I expected and the solution I came up with was just to use the Portaudio ring buffer. I needed to add pa_ringbuffer.[ch] and pa_memorybarrier.h to my project and then define a MessageData structure to store in the ring buffer.
typedef struct MessageData {
MessageType type;
union {
struct {
NSUInteger position;
} position;
} data;
} MessageData;
Then I allocated some space to store 32 messages and created the ring buffer.
_playbackData->RTToMainBuffer = malloc(sizeof(MessageData) * 32);
PaUtil_InitializeRingBuffer(&_playbackData->RTToMainRB, sizeof(MessageData),
32, _playbackData->RTToMainBuffer);
Finally I started an NSTimer for every 20ms to pull data from the ring buffer
while (PaUtil_GetRingBufferReadAvailable(&_playbackData->RTToMainRB)) {
MessageData *dataPtr1, *dataPtr2;
ring_buffer_size_t sizePtr1, sizePtr2;
// Should we read more than one at a time?
if (PaUtil_GetRingBufferReadRegions(&_playbackData->RTToMainRB, 1,
(void *)&dataPtr1, &sizePtr1,
(void *)&dataPtr2, &sizePtr2) != 1) {
continue;
}
// Parse message
switch (dataPtr1->type) {
case MessageTypeEOS:
break;
case MessageTypePosition:
break;
default:
break;
}
PaUtil_AdvanceRingBufferReadIndex(&_playbackData->RTToMainRB, 1);
}
Then in the realtime thread, pushing a message to the ringbuffer was simply
MessageData *dataPtr1, *dataPtr2;
ring_buffer_size_t sizePtr1, sizePtr2;
if (PaUtil_GetRingBufferWriteRegions(&data->RTToMainRB, 1,
(void *)&dataPtr1, &sizePtr1,
(void *)&dataPtr2, &sizePtr2)) {
dataPtr1->type = MessageTypePosition;
dataPtr1->data.position.position = currentPosition;
PaUtil_AdvanceRingBufferWriteIndex(&data->RTToMainRB, 1);
}
A ringbuffer is a good solution. Two if you need to communicate both ways ie. inbox/outbox message passing.
This is a good implementation for iOS/Mac if you don't want to use Portaudio.
https://github.com/michaeltyson/TPCircularBuffer
I'm trying to run a serial communication example, in order to send data from an Arduino to a Cocoa application following the provided code in http://playground.arduino.cc/Interfacing/Cocoa ( IOKit/ioctl method ). It works, but I cannot stop the receiver thread once started.
I've implemented a switch button ( Start/Stop ) which at start time opens the serial port and launches the receiver thread:
- (IBAction) startButton: (NSButton *) btn {
(…)
error = [self openSerialPort: [SelectPort titleOfSelectedItem] baud:[Baud intValue]];
(…)
[self refreshSerialList:[SelectPort titleOfSelectedItem]];
[self performSelectorInBackground:#selector(incomingTextUpdateThread:) withObject:[NSThread currentThread]];
(…)
}
The thread code is practically the same as in the example, excepting that I've included code to rebuild the serial packet from received buffers and save it to a SQLite database:
- (void)incomingTextUpdateThread: (NSThread *) parentThread {
// mark that the thread is running
readThreadRunning = TRUE;
const int BUFFER_SIZE = 100;
char byte_buffer[BUFFER_SIZE]; // buffer for holding incoming data
int numBytes=0; // number of bytes read during read
(…)
// assign a high priority to this thread
[NSThread setThreadPriority:1.0];
// this will loop until the serial port closes
while(TRUE) {
// read() blocks until some data is available or the port is closed
numBytes = (int) read(serialFileDescriptor, byte_buffer, BUFFER_SIZE); // read up to the size of the buffer
if(numBytes>0) {
// format serial data into packets, but first append at start the end of last read
buffer = [[NSMutableString alloc] initWithBytes:byte_buffer length:numBytes encoding:NSASCIIStringEncoding];
if (status == 1 && [ipacket length] != 0) {
[buffer insertString:ipacket atIndex:0];
numBytes = (int) [buffer length];
}
ipacket = [self processSerialData:buffer length:numBytes]; // Recompose data and save to database.
} else {
break; // Stop the thread if there is an error
}
}
// make sure the serial port is closed
if (serialFileDescriptor != -1) {
close(serialFileDescriptor);
serialFileDescriptor = -1;
}
// mark that the thread has quit
readThreadRunning = FALSE;
}
I try to close the port in the main thread with this code, also part of the startButton selector, following the provided example:
if (serialFileDescriptor != -1) {
[self appendToIncomingText:#"Trying to close the serial port...\n"];
close(serialFileDescriptor);
serialFileDescriptor = -1;
// Revisar... crec que el thread no s'adona que s'ha tancat el file descriptor...
// wait for the reading thread to die
while(readThreadRunning);
// re-opening the same port REALLY fast will fail spectacularly... better to sleep a sec
sleep(0.5);
//[btn setTitle:#"Start"];
[Start setTitle:#"Start"];
}
But it seems that the receiver thread is not aware of the status change in global variable serialFileDescriptor.
So, startButton: opens the port, spawns off a thread to start reading from it, and then immediately closes the port? That's not going to turn out well.
startButton: should not close the port. Leave that for the reading thread to do when it's done, and do it on the main thread only when you need to close the port for some other reason (e.g., quitting).
Global variables are, by definition, visible throughout the program, and this includes across thread boundaries. If readThreadRunning is not getting set to FALSE (which assumes that FALSE hasn't been defined to something exotic), then your read thread's loop must still be running. Either it is still reading data, or read is blocked (it is waiting for more data).
Note that read has no way to know whether there will be more data. As your comment in the code says, it will block until either it has some data to return or the port gets closed. You should either work out a way to know ahead of time how much data you'll need to read, and stop when you've read that much, or see if you can close the port at the opposite end when everything has been sent and received.
I have a C++ pipe server app and a C# pipe client app communicating via Windows named pipe (duplex, message mode, wait/blocking in separate read thread).
It all works fine (both sending and receiving data via the pipe) until I try and write to the pipe from the client in response to a forms 'textchanged' event. When I do this, the client hangs on the pipe write call (or flush call if autoflush is off). Breaking into the server app reveals it's also waiting on the pipe ReadFile call and not returning.
I tried running the client write on another thread -- same result.
Suspect some sort of deadlock or race condition but can't see where... don't think I'm writing to the pipe simultaneously.
Update1: tried pipes in byte mode instead of message mode - same lockup.
Update2: Strangely, if (and only if) I pump lots of data from the server to the client, it cures the lockup!?
Server code:
DWORD ReadMsg(char* aBuff, int aBuffLen, int& aBytesRead)
{
DWORD byteCount;
if (ReadFile(mPipe, aBuff, aBuffLen, &byteCount, NULL))
{
aBytesRead = (int)byteCount;
aBuff[byteCount] = 0;
return ERROR_SUCCESS;
}
return GetLastError();
}
DWORD SendMsg(const char* aBuff, unsigned int aBuffLen)
{
DWORD byteCount;
if (WriteFile(mPipe, aBuff, aBuffLen, &byteCount, NULL))
{
return ERROR_SUCCESS;
}
mClientConnected = false;
return GetLastError();
}
DWORD CommsThread()
{
while (1)
{
std::string fullPipeName = std::string("\\\\.\\pipe\\") + mPipeName;
mPipe = CreateNamedPipeA(fullPipeName.c_str(),
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
KTxBuffSize, // output buffer size
KRxBuffSize, // input buffer size
5000, // client time-out ms
NULL); // no security attribute
if (mPipe == INVALID_HANDLE_VALUE)
return 1;
mClientConnected = ConnectNamedPipe(mPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
if (!mClientConnected)
return 1;
char rxBuff[KRxBuffSize+1];
DWORD error=0;
while (mClientConnected)
{
Sleep(1);
int bytesRead = 0;
error = ReadMsg(rxBuff, KRxBuffSize, bytesRead);
if (error == ERROR_SUCCESS)
{
rxBuff[bytesRead] = 0; // terminate string.
if (mMsgCallback && bytesRead>0)
mMsgCallback(rxBuff, bytesRead, mCallbackContext);
}
else
{
mClientConnected = false;
}
}
Close();
Sleep(1000);
}
return 0;
}
client code:
public void Start(string aPipeName)
{
mPipeName = aPipeName;
mPipeStream = new NamedPipeClientStream(".", mPipeName, PipeDirection.InOut, PipeOptions.None);
Console.Write("Attempting to connect to pipe...");
mPipeStream.Connect();
Console.WriteLine("Connected to pipe '{0}' ({1} server instances open)", mPipeName, mPipeStream.NumberOfServerInstances);
mPipeStream.ReadMode = PipeTransmissionMode.Message;
mPipeWriter = new StreamWriter(mPipeStream);
mPipeWriter.AutoFlush = true;
mReadThread = new Thread(new ThreadStart(ReadThread));
mReadThread.IsBackground = true;
mReadThread.Start();
if (mConnectionEventCallback != null)
{
mConnectionEventCallback(true);
}
}
private void ReadThread()
{
byte[] buffer = new byte[1024 * 400];
while (true)
{
int len = 0;
do
{
len += mPipeStream.Read(buffer, len, buffer.Length);
} while (len>0 && !mPipeStream.IsMessageComplete);
if (len==0)
{
OnPipeBroken();
return;
}
if (mMessageCallback != null)
{
mMessageCallback(buffer, len);
}
Thread.Sleep(1);
}
}
public void Write(string aMsg)
{
try
{
mPipeWriter.Write(aMsg);
mPipeWriter.Flush();
}
catch (Exception)
{
OnPipeBroken();
}
}
If you are using separate threads you will be unable to read from the pipe at the same time you write to it. For example, if you are doing a blocking read from the pipe then a subsequent blocking write (from a different thread) then the write call will wait/block until the read call has completed and in many cases if this is unexpected behavior your program will become deadlocked.
I have not tested overlapped I/O, but it MAY be able to resolve this issue. However, if you are determined to use synchronous calls then the following models below may help you to solve the problem.
Master/Slave
You could implement a master/slave model in which the client or the server is the master and the other end only responds which is generally what you will find the MSDN examples to be.
In some cases you may find this problematic in the event the slave periodically needs to send data to the master. You must either use an external signaling mechanism (outside of the pipe) or have the master periodically query/poll the slave or you can swap the roles where the client is the master and the server is the slave.
Writer/Reader
You could use a writer/reader model where you use two different pipes. However, you must associate those two pipes somehow if you have multiple clients since each pipe will have a different handle. You could do this by having the client send a unique identifier value on connection to each pipe which would then let the server associate the two pipes. This number could be the current system time or even a unique identifier that is global or local.
Threads
If you are determined to use the synchronous API you can use threads with the master/slave model if you do not want to be blocked while waiting for a message on the slave side. You will however want to lock the reader after it reads a message (or encounters the end of a series of message) then write the response (as the slave should) and finally unlock the reader. You can lock and unlock the reader using locking mechanisms that put the thread to sleep as these would be most efficient.
Security Problem With TCP
The loss going with TCP instead of named pipes is also the biggest possible problem. A TCP stream does not contain any security natively. So if security is a concern you will have to implement that and you have the possibility of creating a security hole since you would have to handle authentication yourself. The named pipe can provide security if you properly set the parameters. Also, to note again more clearly: security is no simple matter and generally you will want to use existing facilities that have been designed to provide it.
I think you may be running into problems with named pipes message mode. In this mode, each write to the kernel pipe handle constitutes a message. This doesn't necessarily correspond with what your application regards a Message to be, and a message may be bigger than your read buffer.
This means that your pipe reading code needs two loops, the inner reading until the current [named pipe] message has been completely received, and the outer looping until your [application level] message has been received.
Your C# client code does have a correct inner loop, reading again if IsMessageComplete is false:
do
{
len += mPipeStream.Read(buffer, len, buffer.Length);
} while (len>0 && !mPipeStream.IsMessageComplete);
Your C++ server code doesn't have such a loop - the equivalent at the Win32 API level is testing for the return code ERROR_MORE_DATA.
My guess is that somehow this is leading to the client waiting for the server to read on one pipe instance, whilst the server is waiting for the client to write on another pipe instance.
It seems to me that what you are trying to do will rather not work as expected.
Some time ago I was trying to do something that looked like your code and got similar results, the pipe just hanged
and it was difficult to establish what had gone wrong.
I would rather suggest to use client in very simple way:
CreateFile
Write request
Read answer
Close pipe.
If you want to have two way communication with clients which are also able to receive unrequested data from server you should
rather implement two servers. This was the workaround I used: here you can find sources.
In Win32, is there a way to test if a socket is non-blocking?
Under POSIX systems, I'd do something like the following:
int is_non_blocking(int sock_fd) {
flags = fcntl(sock_fd, F_GETFL, 0);
return flags & O_NONBLOCK;
}
However, Windows sockets don't support fcntl(). The non-blocking mode is set using ioctl with FIONBIO, but there doesn't appear to be a way to get the current non-blocking mode using ioctl.
Is there some other call on Windows that I can use to determine if the socket is currently in non-blocking mode?
A slightly longer answer would be: No, but you will usually know whether or not it is, because it is relatively well-defined.
All sockets are blocking unless you explicitly ioctlsocket() them with FIONBIO or hand them to either WSAAsyncSelect or WSAEventSelect. The latter two functions "secretly" change the socket to non-blocking.
Since you know whether you have called one of those 3 functions, even though you cannot query the status, it is still known. The obvious exception is if that socket comes from some 3rd party library of which you don't know what exactly it has been doing to the socket.
Sidenote: Funnily, a socket can be blocking and overlapped at the same time, which does not immediately seem intuitive, but it kind of makes sense because they come from opposite paradigms (readiness vs completion).
Previously, you could call WSAIsBlocking to determine this. If you are managing legacy code, this may still be an option.
Otherwise, you could write a simple abstraction layer over the socket API. Since all sockets are blocking by default, you could maintain an internal flag and force all socket ops through your API so you always know the state.
Here is a cross-platform snippet to set/get the blocking mode, although it doesn't do exactly what you want:
/// #author Stephen Dunn
/// #date 10/12/15
bool set_blocking_mode(const int &socket, bool is_blocking)
{
bool ret = true;
#ifdef WIN32
/// #note windows sockets are created in blocking mode by default
// currently on windows, there is no easy way to obtain the socket's current blocking mode since WSAIsBlocking was deprecated
u_long flags = is_blocking ? 0 : 1;
ret = NO_ERROR == ioctlsocket(socket, FIONBIO, &flags);
#else
const int flags = fcntl(socket, F_GETFL, 0);
if ((flags & O_NONBLOCK) && !is_blocking) { info("set_blocking_mode(): socket was already in non-blocking mode"); return ret; }
if (!(flags & O_NONBLOCK) && is_blocking) { info("set_blocking_mode(): socket was already in blocking mode"); return ret; }
ret = 0 == fcntl(socket, F_SETFL, is_blocking ? flags ^ O_NONBLOCK : flags | O_NONBLOCK);
#endif
return ret;
}
I agree with the accepted answer, there is no official way to determine the blocking state of a socket on Windows. In case you get a socket from a third party (let's say, you are a TLS library and you get the socket from upper layer) you cannot decide if it is in blocking state or not.
Despite this I have a working, unofficial and limited solution for the problem which works for me for a long time.
I attempt to read 0 bytes from the socket. In case it is a blocking socket it will return 0, in case it is a non-blocking it will return -1 and GetLastError equals WSAEWOULDBLOCK.
int IsBlocking(SOCKET s)
{
int r = 0;
unsigned char b[1];
r = recv(s, b, 0, 0);
if (r == 0)
return 1;
else if (r == -1 && GetLastError() == WSAEWOULDBLOCK)
return 0;
return -1; /* In case it is a connection socket (TCP) and it is not in connected state you will get here 10060 */
}
Caveats:
Works with UDP sockets
Works with connected TCP sockets
Doesn't work with unconnected TCP sockets