wanderanimrod

wanderanimrod

Finding the file descriptor for an open long-lived http connection

Hello hivemind,

Is there way to find the file descriptor associated with a long-lived tcp connection in elixir / erlang? I am using the HTTPoison library (and hence :hackney) for http calls. I need to send the file descriptor to a server. The client-server interaction goes like this:

  1. Client opens a long-lived http connection to server (using HTTP GET with Keep-alive header)
  2. The server accepts the connection and waits for a payload from the client
  3. The client finds the file descriptor associated with the connection (which is a path on the client’s local file system in /proc/${PID}/fd)
  4. The client sends the file descriptor to the server.

I couldn’t find any API on HTTPoison or hackney to get connection file descriptors, so I attempted the following:

# start a custom hackney pool with long connection timeout to ensure long-lived connections
:ok = :hackney_pool.start_pool(:my_pool, [timeout: 60000, max_connections: 1])

# Find the PID of `:my_pool`
my_pool_pid =  :hackney_pool.find_pool(:my_pool)

# make http request.
{:ok, _} = HTTPoison.get "http://localhost:8000", [], hackney: [pool: :my_pool]

# List all open ports 
open_tcp_port = 
  :erlang.ports()
   |> Enum.map(fn p -> :erlang.port_info(p, :connected) end)
   |> Enum.find(fn {:connected, p} -> p == my_pool_pid end)
#[
#  name: 'tcp_inet',
#  links: [#PID<0.285.0>],
# id: 288,
#  connected: #PID<0.285.0>,
#  input: 0,
#  output: 68,
#  os_pid: :undefined
#]

# Ask erlang to print out a list of open sockets. Notice that the only open socket has Port=288,
# which is the `id` of `open_tcp_port`.
:inet.i
#Port Module   Recv Sent Owner     Local Address   Foreign Address State        Type
#288  inet_tcp 147  68   <0.285.0> localhost:63617 localhost:irdmi CONNECTED(O) STREAM
#:ok

Question
How can I get from the open_tcp_port and / or the socket information from inet.i to a file descriptor path?

Thanks in advance.

Marked As Solved

wanderanimrod

wanderanimrod

I found a solution.

# start a custom hackney pool with long connection timeout to ensure long-lived connections
:ok = :hackney_pool.start_pool(:my_pool, [timeout: 60000, max_connections: 1])

# Find the PID of `:my_pool`
my_pool_pid =  :hackney_pool.find_pool(:my_pool)

# make an http request. This should create a long-lived connection if the server supports it
{:ok, _} = HTTPoison.get "http://localhost:8000", [], hackney: [pool: :my_pool]

# Find the open port associated with the connection
connection_port =
  :erlang.ports()
  |> Enum.find(
    fn port ->
       port_info = :erlang.port_info(port)
       port_info[:connected] == my_pool_pid
     end
    )
{:ok, file_descriptor} = :prim_inet.getfd(connection_port)

Where Next?

Popular in Questions Top

tduccuong
Hi, is there any work on GUI with Elixir, that is similar to Electron/Javascript? My idea is to bundle Phoenix and BEAM into a single se...
New
Werner
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”: 14:57:30.512 [warn] ...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
Kagamiiiii
Student &amp; New to elixir. Nice language. I want to convert a english character, e.g. “a”, which is stored in a variable, to it’s asci...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
chewm
Hi guys, nice to meet you to the whole forum, I’m new here, I’m trying to configure visual studio code for elixir, right now the intellis...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
idi527
I’ve been re-reading swift book again and noticed that multiline strings there don’t have a trailing line break, unlike in elixir iex(2)...
New

Other popular topics Top

peerreynders
Manning 2016 Halloween weekend sale via Deal of the Day Friday, October 28 - Half off all MEAPs - code WM102816LT Saturday, October 29 ...
326 29600 154
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 27727 240
New
Nvim
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
New

We're in Beta

About us Mission Statement