Move echo_server to tests
This commit is contained in:
81
test/echo_server.gleam
Normal file
81
test/echo_server.gleam
Normal file
@@ -0,0 +1,81 @@
|
||||
import gleam/erlang/process.{type Subject}
|
||||
import gleam/io
|
||||
import gleam/otp/actor
|
||||
import gleam/result
|
||||
import gleam/string
|
||||
|
||||
import tcp/reason.{type Reason}
|
||||
import tcp/tcp
|
||||
|
||||
pub type Message {
|
||||
Shutdown
|
||||
ReadyToAccept(subject: Subject(Message), listen_socket: tcp.Socket)
|
||||
}
|
||||
|
||||
pub fn new(socket_path: String) -> Result(tcp.Socket, String) {
|
||||
let server = actor.new(Nil) |> actor.on_message(handle_message) |> actor.start
|
||||
|
||||
case tcp.listen(socket_path), server {
|
||||
Error(r), _ -> Error(reason.to_string(r))
|
||||
_, Error(start_error) ->
|
||||
case start_error {
|
||||
actor.InitExited(_) -> Error("InitExited")
|
||||
actor.InitFailed(_) -> Error("InitFailed")
|
||||
actor.InitTimeout -> Error("InitTimeout")
|
||||
}
|
||||
Ok(listen_socket), Ok(b) -> {
|
||||
let subject = b.data
|
||||
actor.send(subject, ReadyToAccept(subject, listen_socket))
|
||||
Ok(listen_socket)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_message(_: Nil, message: Message) -> actor.Next(Nil, Message) {
|
||||
case message {
|
||||
Shutdown -> actor.stop()
|
||||
|
||||
ReadyToAccept(subject, listen_socket) -> {
|
||||
case tcp.accept(listen_socket) {
|
||||
Error(r) ->
|
||||
actor.stop_abnormal(
|
||||
"Could not accept connection :" <> reason.to_string(r),
|
||||
)
|
||||
Ok(socket) -> {
|
||||
case receive_from_connection(socket) {
|
||||
Error(r) ->
|
||||
io.println_error(
|
||||
"Failed to receive from connection :" <> reason.to_string(r),
|
||||
)
|
||||
Ok(_) -> Nil
|
||||
}
|
||||
|
||||
actor.send(subject, ReadyToAccept(subject, listen_socket))
|
||||
actor.continue(Nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn receive_from_connection(socket: tcp.Socket) -> Result(Nil, Reason) {
|
||||
result.try(receive_until_closed(socket, ""), fn(data) {
|
||||
let _ = tcp.send(socket, data)
|
||||
tcp.close(socket)
|
||||
Ok(Nil)
|
||||
})
|
||||
}
|
||||
|
||||
fn receive_until_closed(
|
||||
socket: tcp.Socket,
|
||||
result: String,
|
||||
) -> Result(String, Reason) {
|
||||
case tcp.receive(socket, 10_000) {
|
||||
Error(reason.Closed) -> Ok(result)
|
||||
Error(err) -> Error(err)
|
||||
Ok(data) -> {
|
||||
let result = data |> string.append(result, _)
|
||||
receive_until_closed(socket, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user