-
Notifications
You must be signed in to change notification settings - Fork 1
Normalize controlled-session protocol and add client readiness #46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,2 @@ | ||
| kind: Added | ||
| body: Freeze, realize, recover, and verify lease-private controlled-session networks and granted workload endpoints, with protocol-v2 session-local coordinates, fixed participant addresses, exact peer firewall grants, and ordinary public or local access preserved only when explicitly granted. | ||
| body: Freeze, realize, recover, and verify lease-private controlled-session networks and granted workload endpoints, with protocol-v1 session-local coordinates, fixed participant addresses, exact peer firewall grants, and ordinary public or local access preserved only when explicitly granted. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
| package controlledsession | ||
|
|
||
| import ( | ||
| "context" | ||
| "errors" | ||
| "fmt" | ||
| "net" | ||
| "sync" | ||
| ) | ||
|
|
||
| // SessionClientV1 is the controller-side owner of one claimed private session | ||
| // connection. It consumes the mandatory opened event during construction and | ||
| // then admits one event read and one request write concurrently. | ||
| type SessionClientV1 struct { | ||
| connection net.Conn | ||
| opened OpenedV1 | ||
| readMu sync.Mutex | ||
| writeMu sync.Mutex | ||
| stateMu sync.RWMutex | ||
| ready bool | ||
| terminated bool | ||
| closeOnce sync.Once | ||
| closeErr error | ||
| } | ||
|
|
||
| func newSessionClientV1(ctx context.Context, connection net.Conn) (*SessionClientV1, error) { | ||
| if ctx == nil || ctx.Done() == nil { | ||
| return nil, fmt.Errorf("open controlled-session client: cancelable context is required") | ||
| } | ||
| if connection == nil { | ||
| return nil, fmt.Errorf("open controlled-session client: connection is required") | ||
| } | ||
| var event EventV1 | ||
| err := withConnectionDeadlineV1(ctx, connection.SetReadDeadline, func() error { | ||
| var readErr error | ||
| event, readErr = ReadEventV1(connection) | ||
| return readErr | ||
| }) | ||
| if err != nil { | ||
| return nil, errors.Join(fmt.Errorf("read controlled-session opened event: %w", err), connection.Close()) | ||
| } | ||
| if event.Kind != EventOpenedV1 || event.Opened == nil { | ||
| return nil, errors.Join(fmt.Errorf("controlled-session first event must be opened"), connection.Close()) | ||
| } | ||
| opened := *event.Opened | ||
| opened.Authorization = cloneAuthorizationV1(event.Opened.Authorization) | ||
| opened.Endpoints = append([]EndpointV1(nil), event.Opened.Endpoints...) | ||
| return &SessionClientV1{connection: connection, opened: opened}, nil | ||
| } | ||
|
|
||
| // Opened returns an independent copy of the immutable session authorization | ||
| // and coordinates received during the connection claim. | ||
| func (client *SessionClientV1) Opened() OpenedV1 { | ||
| opened := client.opened | ||
| opened.Authorization = cloneAuthorizationV1(client.opened.Authorization) | ||
| opened.Endpoints = append([]EndpointV1(nil), client.opened.Endpoints...) | ||
| return opened | ||
| } | ||
|
|
||
| // Ready reports whether the host has verified workload startup and activated | ||
| // the lifecycle. It becomes true only after ReadEvent returns the one ready | ||
| // event and never becomes false. | ||
| func (client *SessionClientV1) Ready() bool { | ||
| client.stateMu.RLock() | ||
| defer client.stateMu.RUnlock() | ||
| return client.ready | ||
| } | ||
|
|
||
| func (client *SessionClientV1) ReadEvent(ctx context.Context) (EventV1, error) { | ||
| if ctx == nil || ctx.Done() == nil { | ||
| return EventV1{}, fmt.Errorf("read controlled-session client event: cancelable context is required") | ||
| } | ||
| client.readMu.Lock() | ||
| defer client.readMu.Unlock() | ||
| var event EventV1 | ||
| err := withConnectionDeadlineV1(ctx, client.connection.SetReadDeadline, func() error { | ||
| var readErr error | ||
| event, readErr = ReadEventV1(client.connection) | ||
| return readErr | ||
| }) | ||
| if err != nil { | ||
| return EventV1{}, errors.Join(fmt.Errorf("read controlled-session client event: %w", err), client.Close()) | ||
| } | ||
| if event.Kind == EventOpenedV1 { | ||
| return EventV1{}, errors.Join(fmt.Errorf("read controlled-session client event: opened may appear only once"), client.Close()) | ||
| } | ||
| if event.Kind == EventReadyV1 { | ||
| client.stateMu.Lock() | ||
| if client.ready { | ||
| client.stateMu.Unlock() | ||
| return EventV1{}, errors.Join(fmt.Errorf("read controlled-session client event: ready may appear only once"), client.Close()) | ||
| } | ||
| client.ready = true | ||
| client.stateMu.Unlock() | ||
| } | ||
| if event.Kind == EventTerminatedV1 { | ||
| client.stateMu.Lock() | ||
| client.terminated = true | ||
| client.stateMu.Unlock() | ||
| } | ||
| return event, nil | ||
| } | ||
|
|
||
| func (client *SessionClientV1) WriteRequest(ctx context.Context, request RequestV1) error { | ||
| if ctx == nil || ctx.Done() == nil { | ||
| return fmt.Errorf("write controlled-session client request: cancelable context is required") | ||
| } | ||
| if err := ValidateRequestV1(request); err != nil { | ||
| return err | ||
| } | ||
| client.writeMu.Lock() | ||
| defer client.writeMu.Unlock() | ||
| client.stateMu.RLock() | ||
| ready := client.ready | ||
| terminated := client.terminated | ||
| client.stateMu.RUnlock() | ||
| if request.Kind == RequestAcknowledgeTerminatedV1 { | ||
| if !terminated { | ||
| return fmt.Errorf("write controlled-session client request: terminal result has not been received") | ||
| } | ||
| } else if terminated { | ||
| return fmt.Errorf("write controlled-session client request: session is terminated") | ||
| } | ||
| if request.Kind != RequestAcknowledgeTerminatedV1 && !ready { | ||
| return fmt.Errorf("write controlled-session client request: session is not ready") | ||
| } | ||
| err := withConnectionDeadlineV1(ctx, client.connection.SetWriteDeadline, func() error { | ||
| return WriteRequestV1(client.connection, request) | ||
| }) | ||
| if err != nil { | ||
| return errors.Join(fmt.Errorf("write controlled-session client request: %w", err), client.Close()) | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| func (client *SessionClientV1) Close() error { | ||
| client.closeOnce.Do(func() { | ||
| client.closeErr = client.connection.Close() | ||
| }) | ||
| return client.closeErr | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| //go:build linux | ||
|
|
||
| package controlledsession | ||
|
|
||
| import ( | ||
| "context" | ||
| "fmt" | ||
| "net" | ||
| "path/filepath" | ||
| ) | ||
|
|
||
| // DialSessionClientV1 claims the Linux lease-private socket exposed only to | ||
| // the controller and consumes its mandatory opened event. | ||
| func DialSessionClientV1(ctx context.Context, socketPath string) (*SessionClientV1, error) { | ||
| if ctx == nil || ctx.Done() == nil { | ||
| return nil, fmt.Errorf("dial controlled-session client: cancelable context is required") | ||
| } | ||
| if !filepath.IsAbs(socketPath) || filepath.Clean(socketPath) != socketPath { | ||
| return nil, fmt.Errorf("dial controlled-session client requires an absolute clean socket path") | ||
| } | ||
| connection, err := (&net.Dialer{}).DialContext(ctx, "unix", socketPath) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("dial controlled-session socket: %w", err) | ||
| } | ||
| return newSessionClientV1(ctx, connection) | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fragment still describes only controlled-session networking, so the newly exposed Linux session client and the protocol's mandatory
readyevent/request gate will be absent from the release notes. Extend this entry or add a separate Changie fragment covering those user-facing changes.AGENTS.md reference: AGENTS.md:L9-L10
Useful? React with 👍 / 👎.