fileshare

package
v0.0.0-...-aa2490a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 4, 2025 License: GPL-3.0 Imports: 28 Imported by: 0

Documentation

Overview

Package fileshare provides gRPC interface for the fileshare functionality.

Index

Constants

View Source
const (
	DirDepthLimit     = 5
	TransferFileLimit = 1000
)

Variables

View Source
var (
	ErrTransferNotFound               = errors.New("transfer not found")
	ErrFileNotFound                   = errors.New("file not found")
	ErrTransferAlreadyAccepted        = errors.New("can't accept already accepted transfer")
	ErrTransferAcceptOutgoing         = errors.New("can't accept outgoing transfer")
	ErrSizeLimitExceeded              = errors.New("provided size limit exceeded")
	ErrAcceptDirNotFound              = errors.New("accept directory not found")
	ErrAcceptDirIsASymlink            = errors.New("accept directory is a symlink")
	ErrAcceptDirIsNotADirectory       = errors.New("accept directory is not a directory")
	ErrNoPermissionsToAcceptDirectory = errors.New("no permissions to accept directory")
	ErrNotificationsAlreadyEnabled    = errors.New("notifications already enabled")
	ErrNotificationsAlreadyDisabled   = errors.New("notifications already disabled")
	ErrTransferCanceledByPeer         = errors.New("transfer has been canceled by peer")
	ErrTransferCanceledByUs           = errors.New("transfer has been canceled by us")
)

Handleable errors

View Source
var (
	IncomingStatus = map[pb.Status]string{
		pb.Status_REQUESTED:            "waiting for download",
		pb.Status_ONGOING:              "downloading",
		pb.Status_SUCCESS:              "completed",
		pb.Status_INTERRUPTED:          "interrupted",
		pb.Status_FINISHED_WITH_ERRORS: "completed with errors",
		pb.Status_ACCEPT_FAILURE:       "accepted with errors",
		pb.Status_CANCELED:             "canceled",
		pb.Status_CANCELED_BY_PEER:     "canceled by peer",
		pb.Status_PENDING:              "pending",
	}
	OutgoingStatus = map[pb.Status]string{
		pb.Status_REQUESTED:            "request sent",
		pb.Status_ONGOING:              "uploading",
		pb.Status_SUCCESS:              "completed",
		pb.Status_INTERRUPTED:          "interrupted",
		pb.Status_FINISHED_WITH_ERRORS: "completed with errors",
		pb.Status_ACCEPT_FAILURE:       "accepted with errors",
		pb.Status_CANCELED:             "canceled",
		pb.Status_CANCELED_BY_PEER:     "canceled by peer",
		pb.Status_FILE_REJECTED:        "the receiver has declined the file transfer",
		pb.Status_PENDING:              "pending",
	}
	FileStatus = map[pb.Status]string{
		pb.Status_SUCCESS:                  "completed",
		pb.Status_CANCELED:                 "canceled",
		pb.Status_INTERRUPTED:              "interrupted",
		pb.Status_PENDING:                  "pending",
		pb.Status_BAD_PATH:                 "the download path is not valid",
		pb.Status_BAD_FILE:                 "the file is no longer found",
		pb.Status_TRANSPORT:                "transport problem",
		pb.Status_BAD_STATUS:               "bad status",
		pb.Status_SERVICE_STOP:             "service not active",
		pb.Status_BAD_TRANSFER:             "bad transfer",
		pb.Status_BAD_TRANSFER_STATE:       "bad transfer state",
		pb.Status_BAD_FILE_ID:              "bad file id",
		pb.Status_BAD_SYSTEM_TIME:          "bad system time",
		pb.Status_TRUNCATED_FILE:           "truncated file",
		pb.Status_EVENT_SEND:               "internal error",
		pb.Status_BAD_UUID:                 "internal error",
		pb.Status_CHANNEL_CLOSED:           "internal error",
		pb.Status_IO:                       "io error",
		pb.Status_DATA_SEND:                "data send error",
		pb.Status_DIRECTORY_NOT_EXPECTED:   "directory not expected",
		pb.Status_EMPTY_TRANSFER:           "empty transfer",
		pb.Status_TRANSFER_CLOSED_BY_PEER:  "transfer closed by peer",
		pb.Status_TRANSFER_LIMITS_EXCEEDED: "directory depth or breadth limits are exceeded",
		pb.Status_MISMATCHED_SIZE:          "the file has been modified",
		pb.Status_UNEXPECTED_DATA:          "the file has been modified",
		pb.Status_INVALID_ARGUMENT:         "internal error",
		pb.Status_TRANSFER_TIMEOUT:         "transfer timeout",
		pb.Status_WS_SERVER:                "waiting for peer to come online",
		pb.Status_WS_CLIENT:                "waiting for peer to come online",
		pb.Status_FILE_MODIFIED:            "the file has been modified",
		pb.Status_FILENAME_TOO_LONG:        "filename too long",
		pb.Status_AUTHENTICATION_FAILED:    "authentication failed",
		pb.Status_FILE_CHECKSUM_MISMATCH:   "the file is corrupted",
	}
	IncomingFileStatus = map[pb.Status]string{
		pb.Status_SUCCESS:              "downloaded",
		pb.Status_CANCELED:             "canceled",
		pb.Status_REQUESTED:            "waiting for download",
		pb.Status_ONGOING:              "downloading",
		pb.Status_FINISHED_WITH_ERRORS: "downloaded with errors",
		pb.Status_ACCEPT_FAILURE:       "accepted with errors",
	}
	OutgoingFileStatus = map[pb.Status]string{
		pb.Status_SUCCESS:              "uploaded",
		pb.Status_CANCELED:             "canceled",
		pb.Status_REQUESTED:            "request sent",
		pb.Status_ONGOING:              "uploading",
		pb.Status_FINISHED_WITH_ERRORS: "uploaded with errors",
		pb.Status_ACCEPT_FAILURE:       "accepted with errors",
	}
)

Functions

func EventToString

func EventToString(event Event) string

func FindTransferFileByPath

func FindTransferFileByPath(tr *pb.Transfer, filePath string) *pb.File

func ForAllFiles

func ForAllFiles(files []*pb.File, op func(*pb.File))

ForAllFiles executes op for all files in files

func GetDefaultDownloadDirectory

func GetDefaultDownloadDirectory() (string, error)

GetDefaultDownloadDirectory returns users Downloads directory or an error if it doesn't exist

func GetSelfPeer

func GetSelfPeer(meshClient meshpb.MeshnetClient) (*meshpb.Peer, error)

GetSelfPeer from meshnet client

func GetTransferFileStatus

func GetTransferFileStatus(file *pb.File, in bool) (status string)

GetTransferFileStatus file status to human readable string

func GetTransferFilesByPathPrefix

func GetTransferFilesByPathPrefix(tr *pb.Transfer, filePath string) []*pb.File

Gets all files with the given path prefix (returns all children of directory)

func GetTransferStatus

func GetTransferStatus(tr *pb.Transfer) string

GetTransferStatus translate transfer status into human readable form

func SetTransferAllFileStatus

func SetTransferAllFileStatus(tr *pb.Transfer, status pb.Status)

SetTransferAllFileStatus reset all files to status

Types

type Action

type Action struct {
	Key    string
	Action string
}

Action represents an action available to the user when notification is displayed

type DbusNotifier

type DbusNotifier struct {
	// contains filtered or unexported fields
}

DbusNotifier wraps github.com/esiqveland/notify notifier implementation

func (*DbusNotifier) Close

func (n *DbusNotifier) Close() error

Close dbus connection. Thread safe.

func (*DbusNotifier) SendNotification

func (n *DbusNotifier) SendNotification(summary string, body string, actions []Action) (uint32, error)

SendNotification sends notification via dbus. Thread safe.

type Event

type Event struct {
	Kind      EventKind
	Timestamp int64
}

type EventCallback

type EventCallback interface {
	Event(event ...Event)
}

type EventKind

type EventKind interface{}

type EventKindFileDownloaded

type EventKindFileDownloaded struct {
	TransferId string
	FileId     string
	FinalPath  string
}

type EventKindFileFailed

type EventKindFileFailed struct {
	TransferId string
	FileId     string
	Status     Status
}

type EventKindFileProgress

type EventKindFileProgress struct {
	TransferId  string
	FileId      string
	Transferred uint64
}

type EventKindFileRejected

type EventKindFileRejected struct {
	TransferId string
	FileId     string
	ByPeer     bool
}

type EventKindFileStarted

type EventKindFileStarted struct {
	TransferId  string
	FileId      string
	Transferred uint64
}

type EventKindFileUploaded

type EventKindFileUploaded struct {
	TransferId string
	FileId     string
}

type EventKindRequestQueued

type EventKindRequestQueued struct {
	Peer       string
	TransferId string
	Files      []QueuedFile
}

type EventKindRequestReceived

type EventKindRequestReceived struct {
	Peer       string
	TransferId string
	Files      []ReceivedFile
}

type EventKindTransferFailed

type EventKindTransferFailed struct {
	Status     Status
	TransferId string
}

type EventKindTransferFinalized

type EventKindTransferFinalized struct {
	TransferId string
	ByPeer     bool
}

type EventKindUnknown

type EventKindUnknown struct{}

type EventManager

type EventManager struct {
	// contains filtered or unexported fields
}

EventManager is responsible for libdrop event handling. It keeps transfer state, distributes events to further subscribers, and uses Storage for transfer state persistence. Thread safe.

func NewEventManager

func NewEventManager(
	isProd bool,
	meshClient meshpb.MeshnetClient,
	osInfo OsInfo,
	filesystem Filesystem,
	defaultDownloadDir string,
) *EventManager

NewEventManager loads transfer state from storage, or creates empty state if loading fails.

func (*EventManager) AcceptTransfer

func (em *EventManager) AcceptTransfer(
	transferID string,
	path string,
	filePaths []string,
) (*pb.Transfer, error)

AcceptTransfer validates the transfer to ensure it can be accepted

func (*EventManager) CancelLiveTransfers

func (em *EventManager) CancelLiveTransfers()

CancelLiveTransfers cancels all ongoing transfers.

func (*EventManager) DisableNotifications

func (em *EventManager) DisableNotifications() error

func (*EventManager) EnableNotifications

func (em *EventManager) EnableNotifications(fileshare Fileshare) error

func (*EventManager) Event

func (em *EventManager) Event(event ...Event)

Event sends an event to the event manager in an asynchronous manner

This function should return immediately, unless the Events channel is full, in which case it will block until there is space

func (*EventManager) GetTransfer

func (em *EventManager) GetTransfer(transferID string) (*pb.Transfer, error)

GetTransfer by ID.

func (*EventManager) GetTransfers

func (em *EventManager) GetTransfers() ([]*pb.Transfer, error)

GetTransfers is used for listing transfers. Returned transfers are sorted by date created from oldest to newest.

func (*EventManager) SetFileshare

func (em *EventManager) SetFileshare(fileshare Fileshare)

SetFileshare must be called before using event manager. Necessary because of circular dependency between event manager and libDrop.

func (*EventManager) SetStorage

func (em *EventManager) SetStorage(storage Storage)

SetStorage must be called before using event manager. Necessary because of circular dependency between event manager and libDrop.

func (*EventManager) Subscribe

func (em *EventManager) Subscribe(id string) <-chan TransferProgressInfo

Subscribe is used to track progress.

type Fileshare

type Fileshare interface {
	// Enable starts service listening at provided address
	Enable(listenAddress netip.Addr) error
	// Disable tears down fileshare service
	Disable() error
	// Send sends the provided file or dir to provided peer and returns transfer ID
	Send(peer netip.Addr, paths []string) (string, error)
	// Accept accepts provided files from provided request and starts download process
	Accept(transferID, dstPath string, fileID string) error
	// Finalize file transfer by ID.
	Finalize(transferID string) error
	// CancelFile id in a transfer
	CancelFile(transferID string, fileID string) error
}

Fileshare defines a set of operations that any type that wants to act as a fileshare service must implement.

type Filesystem

type Filesystem interface {
	fs.StatFS
	fs.ReadDirFS
	Statfs(path string) (unix.Statfs_t, error)
	Lstat(path string) (fs.FileInfo, error)
}

Filesystem defines file operations used by fileshare

type LiveFile

type LiveFile struct {
	ID          string
	FullPath    string
	Size        uint64
	Transferred uint64
	Finished    bool
}

LiveFile is part of LiveTransfer

type LiveTransfer

type LiveTransfer struct {
	ID               string
	Direction        pb.Direction
	TotalSize        uint64
	TotalTransferred uint64
	Files            map[string]*LiveFile // Key is ID
}

LiveTransfer to track ongoing transfers live in app based on events

type NotificationManager

type NotificationManager struct {
	// contains filtered or unexported fields
}

NotificationManager is responsible for creating gui pop-up notifications for changes in transfer file status

func NewNotificationManager

func NewNotificationManager(fileshare Fileshare, eventManager *EventManager) (*NotificationManager, error)

NewNotificationManager creates a new notification

func (*NotificationManager) AcceptTransfer

func (nm *NotificationManager) AcceptTransfer(notificationID uint32)

AcceptTransfer associated with notificationID, generates notifications on failure

func (*NotificationManager) CancelTransfer

func (nm *NotificationManager) CancelTransfer(notificationID uint32)

CancelTransfer associated with notificationID, generates error notifiacation on failure

func (*NotificationManager) CloseNotification

func (nm *NotificationManager) CloseNotification(notificationID uint32)

CloseNotification cleans up any data associated with notificationID

func (*NotificationManager) Disable

func (nm *NotificationManager) Disable()

func (*NotificationManager) NotifyAutoacceptFailed

func (nm *NotificationManager) NotifyAutoacceptFailed(transferID string, peer string, reason error)

NotifyAutoacceptFailed creates a pop-up gui notification

func (*NotificationManager) NotifyFile

func (nm *NotificationManager) NotifyFile(filename string, direction pb.Direction, status pb.Status)

NotifyFile creates a pop-up gui notification, in case of incoming files, filename should be a full path (download path + filename), so that it can be opened by the user.

func (*NotificationManager) NotifyNewAutoacceptTransfer

func (nm *NotificationManager) NotifyNewAutoacceptTransfer(transferID string, peer string)

NotifyNewAutoacceptTransfer creates a pop-up gui notification

func (*NotificationManager) NotifyNewTransfer

func (nm *NotificationManager) NotifyNewTransfer(transferID string, peer string)

NotifyTransfer creates a pop-up gui notification

func (*NotificationManager) OpenFile

func (nm *NotificationManager) OpenFile(notificationID uint32)

OpenFile associated with notificationID

type Notifier

type Notifier interface {
	SendNotification(summary string, body string, actions []Action) (uint32, error)
	Close() error
}

Notifier is responsible for sending notifications to the user

type OsInfo

type OsInfo interface {
	CurrentUser() (*user.User, error)
	GetGroupIds(*user.User) ([]string, error)
}

type PubkeyProvider

type PubkeyProvider struct {
	// contains filtered or unexported fields
}

PubkeyProvider for libdrop

func NewPubkeyProvider

func NewPubkeyProvider(meshClient meshpb.MeshnetClient) *PubkeyProvider

NewPubkeyProvider must be used to create PubkeyProvider

func (*PubkeyProvider) PubkeyFunc

func (c *PubkeyProvider) PubkeyFunc(peerIP string) []byte

PubkeyFunc is called by libdrop on incoming requests to verify their validity

type QueuedFile

type QueuedFile struct {
	BaseDir *string
	Id      string
	Path    string
	Size    uint64
}

type ReceivedFile

type ReceivedFile struct {
	Id   string
	Path string
	Size uint64
}

type Server

type Server struct {
	pb.UnimplementedFileshareServer
	// contains filtered or unexported fields
}

Server implements fileshare rpc receiver

func NewServer

func NewServer(
	fileshare Fileshare,
	eventManager *EventManager,
	meshClient meshpb.MeshnetClient,
	filesystem Filesystem,
	osInfo OsInfo,
	listChunkSize int,
	shutdownChan chan<- struct{},
) *Server

NewServer is a default constructor for a fileshare server

func (*Server) Accept

func (s *Server) Accept(req *pb.AcceptRequest, srv pb.Fileshare_AcceptServer) error

Accept rpc

func (*Server) Cancel

func (s *Server) Cancel(
	ctx context.Context,
	req *pb.CancelRequest,
) (*pb.Error, error)

Cancel rpc

func (*Server) CancelFile

func (s *Server) CancelFile(ctx context.Context, req *pb.CancelFileRequest) (*pb.Error, error)

CancelFile rpc

func (*Server) List

func (s *Server) List(_ *pb.Empty, srv pb.Fileshare_ListServer) error

List rpc

func (*Server) Ping

func (*Server) Ping(ctx context.Context, _ *pb.Empty) (*pb.Empty, error)

Ping rpc

func (*Server) PurgeTransfersUntil

func (s *Server) PurgeTransfersUntil(ctx context.Context, req *pb.PurgeTransfersUntilRequest) (*pb.Error, error)

func (*Server) Send

func (s *Server) Send(req *pb.SendRequest, srv pb.Fileshare_SendServer) error

Send rpc

func (*Server) SetNotifications

func (*Server) Stop

func (s *Server) Stop(ctx context.Context, _ *pb.Empty) (*pb.Empty, error)

Stop rpc

type Status

type Status struct {
	OsErrorCode *int32
	Status      StatusCode
}

type StatusCode

type StatusCode uint
const (
	// Not an error per se; indicates finalized transfers.
	StatusCodeFinalized StatusCode = 1
	// An invalid path was provided.
	// File path contains invalid components (e.g. parent `..`).
	StatusCodeBadPath StatusCode = 2
	// Failed to open the file or file doesn’t exist when asked to download. Might
	// indicate bad API usage. For Unix platforms using file descriptors, it might
	// indicate invalid FD being passed to libdrop.
	StatusCodeBadFile StatusCode = 3
	// Invalid input transfer ID passed.
	StatusCodeBadTransfer StatusCode = 4
	// An error occurred during the transfer and it cannot continue. The most probable
	// reason is the error occurred on the peer’s device or other error that cannot be
	// categorize elsewhere.
	StatusCodeBadTransferState StatusCode = 5
	// Invalid input file ID passed when.
	StatusCodeBadFileId StatusCode = 6
	// General IO error. Check the logs and contact libdrop team.
	StatusCodeIoError StatusCode = 7
	// Transfer limits exceeded. Limit is in terms of depth and breadth for
	// directories.
	StatusCodeTransferLimitsExceeded StatusCode = 8
	// The file size has changed since adding it to the transfer. The original file was
	// modified while not in flight in such a way that its size changed.
	StatusCodeMismatchedSize StatusCode = 9
	// An invalid argument was provided either as a function argument or
	// invalid config value.
	StatusCodeInvalidArgument StatusCode = 10
	// The WebSocket server failed to bind because of an address collision.
	StatusCodeAddrInUse StatusCode = 11
	// The file was modified while being uploaded.
	StatusCodeFileModified StatusCode = 12
	// The filename is too long which might be due to the fact the sender uses
	// a filesystem supporting longer filenames than the one which’s downloading the
	// file.
	StatusCodeFilenameTooLong StatusCode = 13
	// A peer couldn’t validate our authentication request.
	StatusCodeAuthenticationFailed StatusCode = 14
	// Persistence error.
	StatusCodeStorageError StatusCode = 15
	// The persistence database is lost. A new database will be created.
	StatusCodeDbLost StatusCode = 16
	// Downloaded file checksum differs from the advertised one. The downloaded
	// file is deleted by libdrop.
	StatusCodeFileChecksumMismatch StatusCode = 17
	// Download is impossible of the rejected file.
	StatusCodeFileRejected StatusCode = 18
	// Action is blocked because the failed condition has been reached.
	StatusCodeFileFailed StatusCode = 19
	// Action is blocked because the file is already transferred.
	StatusCodeFileFinished StatusCode = 20
	// Transfer requested with empty file list.
	StatusCodeEmptyTransfer StatusCode = 21
	// Transfer resume attempt was closed by peer for no reason. It might indicate
	// temporary issues on the peer’s side. It is safe to continue to resume the
	// transfer.
	StatusCodeConnectionClosedByPeer StatusCode = 22
	// Peer’s DDoS protection kicked in.
	// Transfer should be resumed after some cooldown period.
	StatusCodeTooManyRequests StatusCode = 23
	// This error code is intercepted from the OS errors. Indicate lack of
	// privileges to do certain operation.
	StatusCodePermissionDenied StatusCode = 24
)

type StdFilesystem

type StdFilesystem struct {
	// contains filtered or unexported fields
}

StdFilesystem is a wrapper for golang std filesystem implementation

func NewStdFilesystem

func NewStdFilesystem(basepath string) StdFilesystem

NewStdFilesystem creates an StdFilesystem instance, basepath is the path prepended to all path arguments

func (StdFilesystem) Lstat

func (stdFs StdFilesystem) Lstat(path string) (fs.FileInfo, error)

Lstat a path

func (StdFilesystem) Open

func (stdFs StdFilesystem) Open(name string) (fs.File, error)

Open a file

func (StdFilesystem) ReadDir

func (stdFs StdFilesystem) ReadDir(path string) ([]fs.DirEntry, error)

ReadDir returns DirEntry for all of the files and directories in path

func (StdFilesystem) Stat

func (stdFs StdFilesystem) Stat(path string) (fs.FileInfo, error)

Stat a path

func (StdFilesystem) Statfs

func (stdFs StdFilesystem) Statfs(path string) (unix.Statfs_t, error)

Statfs returns info about filesystem

type StdOsInfo

type StdOsInfo struct{}

func (StdOsInfo) CurrentUser

func (StdOsInfo) CurrentUser() (*user.User, error)

func (StdOsInfo) GetGroupIds

func (StdOsInfo) GetGroupIds(user *user.User) ([]string, error)

type Storage

type Storage interface {
	Load() (map[string]*pb.Transfer, error)
	PurgeTransfersUntil(until time.Time) error
}

Storage is used for filesharing history persistence

type TransferProgressInfo

type TransferProgressInfo struct {
	TransferID  string
	Transferred uint32 // percent of transferred bytes
	Status      pb.Status
}

TransferProgressInfo info to report to the user

Directories

Path Synopsis
Package libdrop wraps libdrop fileshare implementation.
Package libdrop wraps libdrop fileshare implementation.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL