LoginSignup
2
0

paiza.ioでelixir その240

Last updated at Posted at 2023-06-30

概要

paiza.ioでelixirやってみた。
練習問題、やってみた。

練習問題

rtmpのHandshakeを実装せよ。

参考にしたページ。

サンプルコード


defmodule ExRTMP.Handshake do
	defstruct [:stage, :buf, :complete, :time, :client_time]
	def new do
		%__MODULE__{stage: :c0, buf: <<>>, complete: false, time: elem(:erlang.timestamp(), 0)}
	end
	def buffer(%__MODULE__{buf: buf} = handshake, new_buf) do
		%{handshake | buf: buf <> new_buf}
	end
	def send_c0(socket) do
		:gen_tcp.send(socket, <<0x03>>)
	end
	def send_c1(socket) do
		time = :erlang.timestamp() 
			|> elem(0) 
			|> Integer.to_string()
		zeros = <<0::8*4>>
		msg = time <> zeros <> rand()
		:gen_tcp.send(socket, msg)
	end
	def send_c2(socket, time) do
		time2 = :erlang.timestamp() 
			|> elem(0)
		msg = <<time::size(32), time2::size(32)>> <> rand()
		:gen_tcp.send(socket, msg)
	end
	def send_s0(socket) do
		:gen_tcp.send(socket, <<0x03>>)
	end
	def send_s1(socket, time) do
		zeros = <<0::8*4>>
		msg = <<time::size(32)>> <> zeros <> rand()
		:gen_tcp.send(socket, msg)
	end
	def send_s2(socket, time, client_time) do
		msg = <<time::size(32), client_time::size(32)>> <> rand()
		:gen_tcp.send(socket, msg)
	end
	def rand do
		fn -> 
			Enum.random('abcdefghijklmnopqrstuvwxyz0123456789') 
		end
		|> Stream.repeatedly()
		|> Enum.take(1528)
		|> to_string
	end
	def parse(%__MODULE__{buf: msg} = handshake) do
		case msg do
		<<0x03::size(8), rest::binary>> ->
			%{handshake | buf: rest, stage: :c1}
		<<time::unsigned-size(32), 0::unsigned-size(32), _garbage::binary-size(1528)>> ->
			%{handshake | buf: <<>>, stage: :c2}
		<<time::unsigned-size(32), time2::unsigned-size(32), _garbage::binary-size(1528), rest::binary>> ->
			%{handshake | buf: <<>>, stage: :c2, complete: true, client_time: time}
		_ ->
			{:invalid, msg}
		end
	end
	def parse(msg) do
		case msg do
		<<0x03::size(8), rest::binary>> ->
			{:s0, rest}
		<<time::size(32), 0::size(32), _garbage::size(1528), rest::binary>> ->
			{:s1, time, rest}
		<<_time::size(32), _time2::size(32), _garbage::binary-size(1528), rest::binary>> ->
			{:s2, rest}
		_ ->
			{:invalid, msg}
		end
	end
end

ExRTMP.Handshake.new
{:ok, socket} = :gen_tcp.connect('media3.scctv.net', 1935, [:binary, active: false])
|> IO.inspect
ExRTMP.Handshake.send_c0(socket)
|> IO.inspect
ExRTMP.Handshake.send_c1(socket)
|> IO.inspect
{:ok, data} = :gen_tcp.recv(socket, 0)
ExRTMP.Handshake.parse(data)
|> IO.inspect


{:ok, data} = :gen_tcp.recv(socket, 0)
ExRTMP.Handshake.parse(data)
|> IO.inspect

time = elem(:erlang.timestamp(), 0)
ExRTMP.Handshake.send_c2(socket, time)
|> IO.inspect

{:ok, data} = :gen_tcp.recv(socket, 0)
ExRTMP.Handshake.parse(data)
|> IO.inspect

実行結果

{:ok, #Port<0.6>}
:ok
:ok
{:s0,
 <<5, 197, 208, 132, 3, 0, 1, 1, 66, 70, 91, 180, 233, 116, 43, 101, 50, 254,
   30, 74, 200, 126, 175, 19, 151, 63, 64, 62, 97, 183, 90, 188, 22, 228, 21,
   177, 219, 137, 238, 59, 246, 128, 209, 17, 46, 207, 7, 116, ...>>}
{:invalid,
 <<147, 150, 12, 203, 30, 12, 99, 200, 251, 233, 51, 30, 57, 246, 111, 168, 234,
   17, 176, 65, 144, 137, 124, 63, 103, 11, 13, 211, 255, 190, 245, 239, 92, 75,
   204, 7, 193, 171, 150, 36, 126, 198, 15, 86, 17, 7, 215, 141, ...>>}
:ok
{:invalid,
 "lj4gtcxizs4rddejegb6ugx4betyz29lynpazi0tfvnz3214pky8livtgavdderm024lqp3fe6xdp5k61v9wod9pkdylipf9yilvos6hx3vtxtzqlsp6is8kzg1zayv4efaw33o9uupgitfsy0zu1zcy4"}



成果物

以上。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0