librarian v0.2.0 SSH.SCP.Send View Source

implements the data transactions involved in unstreamed SCP file transfer to the destination server.

Concretely, the following functions are implemented:

Link to this section Summary

Functions

initializes the sending procedure for SCP.

responds to information returned on the stderr stream by the scp -t command.

responds to information returned on the stdout stream by the scp -t command.

handles the host scp agent not calling back

postprocesses results sent to the ssh stream.

Link to this section Functions

Specs

init(SSH.Stream.t(), {Path.t(), String.t() | iodata(), integer()}) ::
  {:ok, SSH.Stream.t()}

initializes the sending procedure for SCP.

Expects the following information:

  • the initialized SSH Stream. This will be modified to include our payload.
  • a triple of: {remote_filepath, data_content, permissions} Permissions should be standard unix permissions scheme, for example 0o644 gives read and write permissions for the owner, and read permissions for everyone else, or 0o400 makes it read-only and only readable to the owner.

The following tasks are performed:

  • As per the SCP protocol, send the control command: C0<permissions> <size> <remote_filepath>.
  • stash the content in the :data field of the stream.
Link to this function

on_stderr(string, stream)

View Source

Specs

on_stderr(term(), SSH.Stream.t()) :: {[term()], SSH.Stream.t()}

responds to information returned on the stderr stream by the scp -t command.

These strings will be saved to the stream as part of an {:stderr, data} tuple.

Specs

on_stdout(binary(), SSH.Stream.t()) :: {[term()], SSH.Stream.t()}

responds to information returned on the stdout stream by the scp -t command.

As per the protocol the following binary responses can be expected:

  • <<0>>: connection acknowledged, send data.
  • <<0>>: data packet receieved, send more data.
  • <<1, error_string>>: some error has occurred.
  • <<2, error_string>>: some fatal error has occurred.

The stream struct keeps track of what data it has sent via the :data field. If this contains data, then that data should be sent. If the the field contains :finished, then the available content has been exhausted.

In general, no data will be emitted by the stream, although nonfatal errors will send an error tuple.

Specs

on_timeout(SSH.Stream.t()) :: {[], SSH.Stream.t()}

handles the host scp agent not calling back

sometimes, the other side will forget to send a packet. In those cases, send a <<0>> packet down the SSH as reminder that we're still here and need a response.

Specs

reducer([error: term(), stderr: String.t()], :ok | {:error, String.t()}) ::
  :ok | {:error, String.t()}

postprocesses results sent to the ssh stream.

The ssh stream is mostly used to return error values. We reduce on that stream as a final step in SSH.send/4. The two tuples we emit during stream processing are {:stderr, string} and {:error, string}. For an {:error, string} value, make that the reduced return value. For {:stderr, string}, send it to the process's standard error as a side effect.