Monitor TCP/IP stream - swift

I am interested in learning Vapor, so I decided to work on a website that displays government issued weather alerts. Alert distribution is done via a TCP/IP data stream (streaming1.naad-adna.pelmorex.com port 8080).
What I have in mind is to use IBM's BlueSocket (https://github.com/IBM-Swift/BlueSocket) to create a socket, though after this point, I gave it a bit of thought but was unable to come to a conclusion on what the next steps would be.
Alerts are streamed over the data stream, so I am aware the socket would need to be opened and listened on but wasn't able to get to much past that.
A few things with the data stream are that the start and end of an alert is detected using the start and end tags of the XML document (alert and /alert). There are no special or proprietary headers added to the data, it's only raw XML. I know some alerts also include an XML declaration so I assume the encoding should be taken into account if the declaration is available.
I was then thinking of using XMLParser to parse the XML and use the data I am interested in from the alert.
So really, the main thing I am struggling with is, when the socket is open, what would be the method to listen to it, determine the start and end of the alert and then pass that XML alert for processing.
I would appreciate any input, I am also not restricted to BlueSocket so if there is a better option for what I am trying to achieve, I would be more than open to it.

So really, the main thing I am struggling with is, when the socket is
open, what would be the method to listen to it, determine the start
and end of the alert and then pass that XML alert for processing.
The method that you should use is read(into data: inout Data). It stores any available data that the server has sent into data. There are a few reasons for this method to fail, such as the connection disconnecting.
Here's an example of how to use it:
import Foundation
import Socket
let s = try Socket.create()
try s.connect(to: "streaming1.naad-adna.pelmorex.com", port: 8080)
while true {
if try Socket.wait(for: [s], timeout: 0, waitForever: true) != nil {
var alert = Data()
try s.read(into: &alert)
if let message = String(data: alert, encoding: .ascii) {
print(message)
}
}
}
s.close()
First create the socket. The default is what we want, a IPv4 TCP Stream.
Second connect() to the server using the hostname and port. Without this step, the socket isn't connected and cannot receive or send any data.
wait() until hostname has sent us some data. It returns a list of sockets that have data available to read.
read() the data, decode it and print it. By default this call will block if there is no data available on the socket.
close() the socket. This is good practice.
You might also like to consider thinking about:
non blocking sockets
error handling
streaming (a single call to read() might not give a complete alert).
I hope this answers your question.

Related

Bidirectional communication of Unix sockets

I'm trying to create a server that sets up a Unix socket and listens for clients which send/receive data. I've made a small repository to recreate the problem.
The server runs and it can receive data from the clients that connect, but I can't get the server response to be read from the client without an error on the server.
I have commented out the offending code on the client and server. Uncomment both to recreate the problem.
When the code to respond to the client is uncommented, I get this error on the server:
thread '' panicked at 'called Result::unwrap() on an Err value: Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }', src/main.rs:77:42
MRE Link
Your code calls set_read_timeout to set the timeout on the socket. Its documentation states that on Unix it results in a WouldBlock error in case of timeout, which is precisely what happens to you.
As to why your client times out, the likely reason is that the server calls stream.read_to_string(&mut response), which reads the stream until end-of-file. On the other hand, your client calls write_all() followed by flush(), and (after uncommenting the offending code) attempts to read the response. But the attempt to read the response means that the stream is not closed, so the server will wait for EOF, and you have a deadlock on your hands. Note that none of this is specific to Rust; you would have the exact same issue in C++ or Python.
To fix the issue, you need to use a protocol in your communication. A very simple protocol could consist of first sending the message size (in a fixed format, perhaps 4 bytes in length) and only then the actual message. The code that reads from the stream would do the same: first read the message size and then the message itself. Even better than inventing your own protocol would be to use an existing one, e.g. to exchange messages using serde.

Get data from UNIX socket with Swift on MacOS

I want to use a UNIX socket on Macos using Swift to receive some bytes, nothing serious. But I can't get to
to read any data from the socket.
Why UNIX socket? I wanted to have a "simple IPC". I could use TCP/IP, but now I want to make this work.
I did create a socket using SocketPort
SocketPort(protocolFamily: AF_UNIX, socketType: SOCK_STREAM, protocol: 0, address: data)
I did created an input stream with:
(...)
CFStreamCreatePairWithSocket(kCFAllocatorDefault, port.socket, &readStream, nil)
(...)
self.inputStream = readStream!.takeRetainedValue()
self.inputStream?.delegate = self
self.inputStream?.schedule(in: RunLoop.current, forMode: .default)
self.inputStream?.open()
And after running the app, everything seems fine, even the StreamDelegate protocol function 'stream' is called
back with eventCode for 'openCompleted' after openning the input stream.
Then I send some data with 'socat' but can't get those bytes in the swift app.
I'm using XCode, I added the network entitlements as I read somewhere. But I can't debug the socket. I expected
the 'stream' function to get called once I send some data to the socket.
I read other projects like BlueSocket (I'll give a try later but is not simple to add it to my existing XCode proyect),
they seem to go low-level ( calling Darwin.socket, Darwin.connect...).
I can provide more code. I don't know where to look at. Any clue? advice?
Thanks!
I solved this years ago by writing my own implementation of URLProtocol. I was using it for Docker, so I added a URL scheme of "docker". The code has a lot of dependencies, but here is a a working commit where you should be able to get the basic idea.

How to produce a response body with asynchronously created body chunks in Swift Vapor

I am looking into the Swift Vapor framework.
I am trying to create a controller class that maps data obtained on an SSL link to a third party system (an Asterisk PBX server..) into a response body that is sent over some time down to the client.
So I need to send received text lines (obtained separately on the SSL connection) as they get in, without waiting for a 'complete response' to be constructed.
Seeing this example:
return Response(status: .ok) { chunker in
for name in ["joe\n", "pam\n", "cheryl\n"] {
sleep(1)
try chunker.send(name)
}
try chunker.close()
}
I thought it might be the way to go.
But what I see connecting to the Vapor server is that the REST call waits for the loop to complete, before the three lines are received as result.
How can I obtain to have try chunker.send(name) send it's characters back the client without first waiting for the loop to complete?
In the real code the controller method can potentially keep an HTTP connection to the client open for a long time, sending Asterisk activity data to the client as soon as it is obtained. So each .send(name) should actually pass immediately data to the client, not waiting for the final .close() call.
Adding a try chunker.flush() did not produce any better result..
HTTP requests aren't really designed to work like that. Different browsers and clients will function differently depending on their implementations.
For instance, if you connect with telnet to the chunker example you pasted, you will see the data is sent every second. But Safari on the other hand will wait for the entire response before displaying.
If you want to send chunked data like this reliably, you should use a protocol like WebSockets that is designed for it.

How can I defense from attackers who send junk data packet?

I wrote a TCP socket program,and define a text protocol format like: "length|content",
to make it simple, the "length" is always 1-byte-long and it define the number of bytes of "content"
My problem is:
when attackers send packets like "1|a51",it will stay in tcp's receive buffer
the program will parse it wrong and the next packet would start like "5|1XXXX",
then the rest of the packets remain in the buffer would all parsed wrong,
how to solve this problem?
If you get garbage, just close the connection. It's not your problem to figure out what they meant, if anything.
instead of length|content only, you also need to provide a checksum, if the checksum is not correct, you should drop the connection to avoid partial receive.
this is a typical problem in tcp protocol, since the tcp is stream based. but just as http, which is an application of tcp protocol, it has a structure of request / response to make sure each end of the connection knows when the data has been fully transferred.
but your scenario is a little bit tricky, since the hacker can only affect the connection of his own. while it cannot change the data from other connections, only if he can control the route / switcher between your application and the users.

Chrome Experimental Socket API: What Does `chrome.experimental.socket.sendTo()` And `recvFrom()` Do?

This week, I messed around with Chromium's Socket API a bit. But there's something which isn't really clear to me about this bad documented experimental interface.
What The docs on Google Code Say:
... about sendTo() at the moment:
Writes data on the given socket.
socketId ( integer ) The socketId.
data ( ArrayBuffer ) The data to
write.
address ( string )
The address of the remote machine.
port (
integer ) The port of the remote machine.
SendToCallback ( function
)
But the description of sendTo() is exactly the same as the description of write() (write - Writes data on the given socket.). It's the same about recvFrom() and read() - both of them have got exactly the same description (read - Reads data from the given socket. / recvFrom - Reads data from the given socket.). But nobody says interesting anything about the differences.
What I Found Out:
It doesn't matter what I'm doing, sendTo always returns the following object:
[-] Object
bytesWritten: -2
[+] __proto__: Object
If I use write instead of sendTo in all these situations, everything happens as expected.
It's the same with recvFrom() and read() - read() is working as expected and recvFrom() fails.
My Question(s):
What is sendTo() for and what's the difference between write()
and sendTo()?
What is recvFrom() for and what's the difference between read() and recvFrom()?
Why are there so many akin methods?
And: Is there anywhere some more information about the Socket API? The Google Code docs are really lightweight. Aren't there any articles on chromium.org concerning that?
Thanks.
Apologies for the confusion. We are rolling out an improvement to the documentation based on your question.
The Chrome socket API is a thin layer over a subset of the POSIX sockets API. It follows the convention that read()/write() are for connected sockets, and sendto()/recvfrom() are for non-connected sockets. At the risk of oversimplifying, you'll want to use the former for connected-oriented protocols (TCP), and the latter for connectionless protocols (UDP). There's a good comparison of why one would choose TCP vs. UDP in the Wikipedia article on UDP.
I don't know much about sockets but I think the docs are mixed up, and sendTo is used when a connection is being initiated from the browser (or the other way around maybe, and the other should be used when a client initiates a socket connection into the browser but I don't see any SocketServer support anywhere so... anyway). From source (check out the parameters):
write()
// Writes data on the given socket.
// |socketId| : The socketId.
// |data| : The data to write.
// |callback| : Called when the first of any of the following happens: the
// write operation completes without blocking, the write operation blocked
// before completion (in which case onEvent() will eventually be called with
// a <code>writeComplete</code> event), or an error occurred.
static void write(long socketId,
ArrayBuffer data,
WriteCallback callback);
sendTo()
// Writes data on the given socket.
// |socketId| : The socketId.
// |data| : The data to write.
// |address| : The address of the remote machine.
// |port| : The port of the remote machine.
// |callback| : Called when the first of any of the following happens: the
// write operation completes without blocking, the write operation blocked
// before completion (in which case onEvent() will eventually be called with
// a <code>writeComplete</code> event), or an error occurred.
static void sendTo(long socketId,
ArrayBuffer data,
DOMString address,
long port,
SendToCallback callback);
You have the rest of the documentation in the link I gave you (experimental_socket.idl).