erlang:is_port/1 and sockets - erlang

I was reading more about erlang:is_port/1 so I decided to test it with several values.
I saw that with normal sockets it replies true if the socket is up and false otherwise (i.e. socket is down).
Can is_port/1 be used also with ssl sockets? I tried but it always returns false.

If you refer to a SSL Socket as the returned value from (for example) ssl:connect/2,3, then the answer is "no". The SSL Sockets in the context of the SSL application are of a sslsocket() type, which, according to the documentation are opaque to the user and definitely not a port. Specifically, they are records:
%% Looks like it does for backwards compatibility reasons
-record(sslsocket, {fd = nil, pid = nil}).

Related

How to disable address filtering in Contiki-NG cc2420 radio module?

When trying to disable address filtering by changing RADIO_PARAM_RX_MODE like below, cc2420 auto ack is not working and motes get duplicated packets.
radio_value_t radio_rx_mode;
NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_mode);
radio_rx_mode &= ~RADIO_RX_MODE_ADDRESS_FILTER;
if(NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE, radio_rx_mode) != RADIO_RESULT_OK) {
LOG_WARN("radio does not support setting RADIO_PARAM_RX_MODE\n");
}else{
LOG_INFO("turned of Address filtering.\n");
}
How to turn off just address filtering?
Your code is the correct way to disable the address recognition / filtering.
Regarding auto-ACK, the CC2420 datasheet says this:
If MDMCTRL0.AUTOACK is enabled, an acknowledge frame is transmitted for all incoming frames accepted by the address recognition with the acknowledge request flag set and a valid CRC. AUTOACK therefore does not make sense unless also ADR_DECODE and AUTOCRC are enabled.
This means that if you have address filtering disabled, you need to send software ACK.

Bonjour: Search for a service by name

I have an application that needs to search and resolve a Bonjour-advertised service whose name is known in advance. Most Bonjour examples I have found related to service discovery are structured more or less like this:
Call browse to detect all services of a given type (for example, this could be _http._tcp)
For each service found, serviceFound is called. Service names are reported here
Call resolve on each service found
For each service resolved, serviceResolved is called
Is it possible with Bonjour to skip the "discovery" stage, since I know in advance the name of the service I want to resolve? Can I just detect and resolve a service with a known name?
1- Answer
Yes, you can start with the 3rd step if you already know the name of the service. This is because this step is performed through a DNS lookup for a SRV record with the name of the service sent to a well-known multicast address. So, no previous information is needed to make this call, and the mDNS responder must be stateless, since the underlying DNS protocol is stateless (each response is bound to a unique request - no state maintained between several requests).
2- Example
Here is an example I've just written with Swift, that has passed tests running on my iPad to find a service running on my Mac Mini.
So, we suppose the domain is local, the service type is _http._tcpand the name of the service is myservice, running on host Mac-mini-de-Alexandre.local and listening to TCP port 8080.
To track informations about the service, for instance its hostname and TCP port, we define a class that implements the NetServiceDelegate protocol:
class MyNetServiceDelegate : NSObject, NetServiceDelegate {
public func netServiceDidResolveAddress(_ sender: NetService) {
print(sender.hostName!, sender.port)
}
}
This new class will be used to instantiate the delegate for a NetService instance.
So, we create a NetService instance corresponding to the service we already know about, that we store in the long-term with a static constant property of some main class:
static let ns = NetService(domain: "local.", type: "_http._tcp.", name: "myservice")
It is stored in the long term because it must not be deallocated before we find our service.
Note that the delegate property in class NetService is declared unowned(unsafe). So, we also need to create a reference to the delegate instance:
static let ns_deleg = MyNetServiceDelegate()
When we want to resolve the service, we may write:
ns.delegate = ns_deleg
ns.resolve(withTimeout: TimeInterval(10))
The delegate instance will be called later (resolve() is a non-blocking method) if the service is found, and in this case, it will print the hostname and port.
Here is the output I got in my Xcode output window:
Mac-mini-de-Alexandre.local. 8080
Finally, note that because of the unowned reference, it would be a mistake to write the following code (the delegate instance would be shortly deallocated):
// bad code -- do not write that -- only here to show a common mistake
ns.delegate = MyNetServiceDelegate()
ns.resolve(withTimeout: TimeInterval(10))
3- Trick to help debugging
Here is a little trick to debug such a mDNS resolution: on a Unix shell (macOS for instance), just run the following line:
dig -p 5353 #224.0.0.251 myservice._http._tcp.local. SRV +short
If an http service with name myservice is running, you will get the host name and port. With my example, you will get the following:
0 0 8080 Mac-mini-de-Alexandre.local.
So, before trying to use the Swift code I've written here, just check that your service is correctly announced with this shell command.
Finally, note that this dig based command only makes one IPv4 mDNS query on each IPv4 network interface, but using the Apple Bonjour API, two groups of mDNS requests are done automatically: one with IPv4 to the multicast destination 224.0.0.251 on each network interface that supports IPv4, and another with IPv6 to the multicast destination ff02::fb on each interface that supports IPv6.

How to send data immediately in epoll ET mode when connect established

My server needs to send data when client connects to it. I am using Epoll ET mode.
But how to do it? Could any one give me a simple example for me?
Assuming you are listening on your socket (socket, bind, listen), and have added it's descriptor to epoll (epoll_create and epoll_ctl), then epoll_wait will tell you when there is a new connection to accept.
First you accept the connection (sockfd is descriptor of socket you're listening on, efd is epoll instance) and add it to your epoll instance:
int connfd = accept4(sockfd, NULL, 0, SOCK_NONBLOCK);
struct epoll_event ev;
ev.events = EPOLLOUT | EPOLLET;
ev.data.fd = connfd;
epoll_ctl(efd, EPOLL_CTL_ADD, connfd, &ev)
Then you go back to your main loop and call epoll_wait again. It will tell you when the socket is ready for writing, and you just happily write or sendfile away.
Add lots of error checking, and probably TCP_CORK and you're done. There's a working example on github.com/grahamking/netshare/.
I hope this gives you enough information to get started.

Read raw data from socket

I have a device that sends data to my server via gprs . The problem is that it sends raw data and i don't know where i can stop the reading
Currently i am using something TIdHttpServer and something like this to read the strings :
var
s : string;
repeat
s:=s+acontext.Connection.Socket.ReadChar;
until acontext.Connection.Socket.InputBufferIsEmpty;
Is there a better solution to my problem ?
TCP is stream oriented. If the protocol is unknown, the server only can try to read into a byte array (if memory is not a problem) or a file stream. If the client disconnects normally, the data is 'complete'. Unfortunately, if the protocol is unknown, the server can not tell wether the client died or disconnected normally.
InputBufferIsEmpty does not help, as it only says if there is data in the (TCP) buffer - and depending on latency this can happen frequently, but it does not mean that there are no more in-flight bytes.
You could try to 'reverse engineer' the protocol, by sending known strings over the client devices. But if the sender is a black box, there can be many special cases - think of encoding or 'escape' characters etc.
You could make up you own protocol.
Some ideas are:
use a special character or characters combo to define the end of the
message.
append at the start of the message some fixed size field with the size of the message

Ruby, SSLSockets, and Apple's Enhanced APN message format

I'm trying to implement support for Apple's enhanced Push Notification message format in my Rails app, and am having some frustrating problems. I clearly don't understand sockets as much as I thought I did.
My main problem is that if I send all messages correctly, my code hangs, because socket.read will block until I receive a message. Apple doesn't return anything if your messages looked OK, so my program locks up.
Here is some pseudocode for how I have this working:
cert = File.read(options[:cert])
ctx = OpenSSL::SSL::SSLContext.new
ctx.key = OpenSSL::PKey::RSA.new(cert, options[:passphrase])
ctx.cert = OpenSSL::X509::Certificate.new(cert)
sock = TCPSocket.new(options[:host], options[:port])
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
ssl.sync = true
ssl.connect
messages.each do |message|
ssl.write(message.to_apn)
end
if read_buffer = ssl.read(6)
process_error_response(read_buffer)
end
Obviously, there are a number of problems with this:
If I'm sending messages to a large number of devices, and the failure message is sent half way through processing, then I'm not going to actually see the error until I've already tried to send to all devices.
As mentioned earlier, if all messages were acceptable to Apple, my app will hang on the socket read call.
One way I've tried to solve this is by to reading from the socket in a separate thread:
Thread.new() {
while data = ssl.read(6)
process_error_response(data)
end
}
messages.each do |message|
ssl.write(message.to_apn)
end
ssl.close
sock.close
This doesn't seem to work. Data never seems to be read from the socket. This is probably a misunderstanding I have about how sockets are supposed to work.
The other solution I have thought of is having a non-blocking read call... but it doesn't seem like Ruby has a non blocking read call on SSLSocket until 1.9... which I unfortunately cannot use right now.
Could someone with a better understanding of socket programming please point me in the right direction?
cam is correct: the traditional way to handle this situation is with IO.select
if IO.select([ssl], nil, nil, 5)
read_buffer = ssl.read(6)
process_error_response(read_buffer)
end
This will check ssl for "readability" for 5 seconds and return ssl if it's readable or nil otherwise.
Can you use IO.select? It lets you specify a timeout, so you could at limit the amount of time you block. See the spec for details: http://github.com/rubyspec/rubyspec/blob/master/core/io/select_spec.rb
I'm interested in this too, this is another approach, unfortunately with it's own flaws.
messages.each do |message|
begin
// Write message to APNS
ssl.write(message.to_apn)
rescue
// Write failed (disconnected), read response
response = ssl.read(6)
// Unpack the binary response and print it out
command, errorCode, identifier = response.unpack('CCN');
puts "Command: #{command} Code: #{errorCode} Identifier: #{identifier}"
// Before reconnecting, the problem (assuming incorrect token) must be solved
break
end
end
This seems to work, and since I'm keeping a persistent connection, I can without problems reconnect in the rescue code and start over again.
There are some issues though. The main problem I'm looking to solve is disconnects caused by sending in incorrect device tokens (for example from development builds). If I have 100 device tokens that I send a message to, and somewhere in the middle there is an incorrect token, my code lets me know which one it was (assuming I supplied good identifiers). I can then remove the faulty token, and send the message to all devices that appeared after the faulty one (since the message didn't get sent to them). But if the incorrect token is somewhere in the end of the 100, the rescue doesn't happen until the next time I send messages.
The problem seams to be that the code isn't really in real time. If I were to send in, say, 10 messages to 10 incorrect tokens with this code, everything would be just fine, the loop will go through and no problems will be reported. It seems that write() doesn't wait for everything to clear up, and the loops runs through before the connection is terminated. The next time the loop will be run, the write() command fails (since we've actually been disconnected since the last time) and we would get the error.
If there is an alternative way to respond to the failed connection, this could solve the problem.
There is a simple way. After you write your messages, try reading in nonblocking mode:
ssl.connect
ssl.sync = true # then ssl.write() flushes immediately
ssl.write(your_packed_frame)
sleep(0.5) # so APN have time to answer
begin
error_packet = ssl.read_nonblock(6) # Read one packet: 6 bytes
# If we are here, there IS an error_packet which we need to process
rescue IO::WaitReadable
# There is no (yet) 6 bytes from APN, probably everything is fine
end
I use it with MRI 2.1 but it should work with earlier versions too.

Resources