provicol

package module
v0.1.4 Latest Latest
Warning

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

Go to latest
Published: Oct 22, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

README

Provicol

How does it work

Provicol is a protocol question based. It's composed of a parent and a child.

The parent ask a question, the child answer, and the parent scan the answer.

The parent needs to connect first, here is the order of the connections:

1. NewParent(path, perms) // give parent
2. NewChild(path) // give child

3. child.Bind(...) {
    child.Reply(...)
}
4. child.Listen()

5. parent.Ask(...).Scan(...)

6. parent.Close()
7. parent.Close()

(Thoses actions are grouped together because of what they do)

Everything in child needs to be implemented in the provider implementation, whild parent needs to be in the main software.

The child replies a buffer with a header

Composition of buffer

Here is first what the header look like

Previous Version ``` { totalSize: uint64 } (8 bytes)
<data>
```
{
    magic:      uint32
    totalSize:  uint64
    isError:    uint32 // it could be bool but no.
} (16 bytes)

<data>

Magic is 0x1b505643 in hex, or this number in decimal 458249795.

The isError is typically 0 or 1.

Ok, with that said, now let's see what each action does:

NewParent

It takes a path and perms, basically, it creates a new unix socket that is bind to listen what the child will say

(note: the parent will remove the socket if it already exists)

It will wait until a new child connects, so be careful, it can freeze the program.

That's why I recommand to use parent.NewParent asynchrously (in a goroutine, or a thread) so the wainting doesnt affect the program.

NewChild

It will connect to a socket given in parametter that a parent created.

File transfers

The Unix socket can also transfer an open file descriptor without putting the file contents in a []byte. This is useful for large local objects.

The parent can send a descriptor as the last handler argument:

response := parent.AskWithFD(source, PutObject, publicKey, bucket, object)
if err := response.Scan(); err != nil {
    return err
}

The handler must accept *os.File as its last argument. Listen closes the received descriptor when the handler returns, so a handler must not retain it:

child.Bind(PutObject, func(publicKey, bucket, object string, source *os.File) error {
    _, err := io.Copy(destination, source)
    return err
})

For downloads, the child can attach a descriptor to its response:

child.Bind(GetObject, func(publicKey, bucket, object string) error {
    file, err := os.Open(path)
    if err != nil {
        return err
    }
    return child.ReplyFD(file)
})

file, err := parent.Ask(GetObject, publicKey, bucket, object).ScanFD()
if err != nil {
    return err
}
defer file.Close()

AskWithFD, ReplyFD and ScanFD require the existing Unix socket connection. File descriptors are local kernel resources and cannot be used over TCP or between machines.

Documentation

Index

Constants

View Source
const (
	Ping    askingBytecode = iota // ( ) -> ( string )
	Connect                       // ( credentials [ ] byte ) -> ( string )

	ListBuckets  // ( pukey string ) -> ( [ ] string )
	CreateBucket // ( pukey string, bucket string ) -> ( )
	DeleteBucket // ( pukey string, bucket string ) -> ( )

	ListObjects    // ( pukey string, bucket string ) -> ( [ ] string )
	GetObject      // ( pukey string, bucket string, object string ) -> ( data []byte or file descriptor )
	PutObject      // ( pukey string, bucket string, object string, data []byte or file descriptor ) -> ( )
	DeleteObject   // ( pukey string, bucket string, object string ) -> ( )
	GetObjectInfos // ( puket string, bucket string, object string ) -> ( date string, size int64, author string )

	ListRepositories // ( id ) -> ( []string )
	CreateRepository // ( id, repo ) -> ( )
	DeleteRepository // ( id, repo ) -> ( )
	ListTags         // ( id, repo ) -> ( []string )

	GetManifest    // ( id, repo, ref ) -> ( mediaType string, digest string, data []byte )
	PutManifest    // ( id, repo, ref, mediaType string, data []byte ) -> ( )
	DeleteManifest // ( id, repo, ref ) -> ( )

	StatBlob        // ( id, repo, digest ) -> ( exists bool, size int64 )
	GetBlobChunk    // ( id, repo, digest, offset, length int64 ) -> ( []byte )
	BeginBlobUpload // ( id, repo ) -> ( uploadID string )
	PutBlobChunk    // ( id, uploadID, offset int64, data []byte ) -> ( )
	CommitBlob      // ( id, uploadID, digest string ) -> ( )

	Capabilities // ( ) -> ( []string )   // "storage", "registry"
)
View Source
const (
	// date used for layour of GetObjectInfos
	ProvicolDateLayout = "2006-01-02 15:04:05"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Child added in v0.0.2

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

func NewChild added in v0.0.2

func NewChild(socketPath string) (*Child, error)

func (*Child) Bind added in v0.0.2

func (l *Child) Bind(op askingBytecode, fn any)

func (*Child) Close added in v0.0.3

func (c *Child) Close() error

func (*Child) Error added in v0.1.0

func (c *Child) Error(what error)

func (*Child) Flush added in v0.0.4

func (c *Child) Flush()

func (*Child) Listen added in v0.0.2

func (l *Child) Listen() error

func (*Child) Reply added in v0.0.4

func (c *Child) Reply(v any)

func (*Child) ReplyFD added in v0.1.4

func (c *Child) ReplyFD(file *os.File) error

ReplyFD attaches a file descriptor to the next response.

type ChildResponse added in v0.0.2

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

func (*ChildResponse) Scan added in v0.0.2

func (r *ChildResponse) Scan(dests ...any) error

func (*ChildResponse) ScanFD added in v0.1.4

func (r *ChildResponse) ScanFD() (*os.File, error)

ScanFD returns the file descriptor attached to a successful response.

type Parent added in v0.0.2

type Parent struct {
	io.Closer
	// contains filtered or unexported fields
}

func NewParent added in v0.0.2

func NewParent(socketPath string, perms os.FileMode) (p *Parent, err error)

func (*Parent) Ask added in v0.0.2

func (m *Parent) Ask(op askingBytecode, args ...any) *ChildResponse

func (*Parent) AskWithFD added in v0.1.4

func (m *Parent) AskWithFD(file *os.File, op askingBytecode, args ...any) *ChildResponse

AskWithFD sends a request together with a file descriptor. The child receives the descriptor as the last argument of its bound handler.

func (*Parent) Close added in v0.0.2

func (m *Parent) Close() error

Jump to

Keyboard shortcuts

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