paiza.ioでelixir その240

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

# 練習問題
rtmpのHandshakeを実装せよ。

# 参考にしたページ。

https://qiita.com/saka1_p/items/152021e375379cc25aad


# サンプルコード

```

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"}



```

# 成果物

https://paiza.io/projects/FfK9Dr5gdAbdEV8--3j2cw

以上。