Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
0d7dd87
add readme
stevemurr Mar 13, 2022
c967a35
update gitignore
stevemurr Mar 13, 2022
ad8e9e4
add project structure
stevemurr Mar 13, 2022
c45945f
port message_data with test
stevemurr Mar 13, 2022
78fc516
change enum to byte
stevemurr Mar 13, 2022
b3e53ba
update test name
stevemurr Mar 13, 2022
ac45155
add message_close and test
stevemurr Mar 13, 2022
b352a7a
add makefile
stevemurr Mar 13, 2022
f27bc4f
add message_eof and test
stevemurr Mar 13, 2022
a0b3253
add message_open and test
stevemurr Mar 13, 2022
2b47afd
normalize variable naming across tests
stevemurr Mar 13, 2022
e2f883e
add message_openconfirm and test
stevemurr Mar 13, 2022
bd234a5
add message_openfailure and test
stevemurr Mar 13, 2022
4adc570
fix message types
stevemurr Mar 13, 2022
368e266
add message_windowadjust and test
stevemurr Mar 13, 2022
5e71855
update makefile
stevemurr Mar 13, 2022
400aa59
refine gitignore
stevemurr Mar 13, 2022
e2507d5
add gostdlib package
stevemurr Mar 13, 2022
bc93afe
add gostdlib tests
stevemurr Mar 13, 2022
895b31f
make message public
stevemurr Mar 14, 2022
1b6d089
add error to gostdlib
stevemurr Mar 14, 2022
0fe6bfa
add codec encoder and decoder
stevemurr Mar 14, 2022
07d4efb
update IReader signature
stevemurr Mar 14, 2022
b95d10d
messages implement Message interface
stevemurr Mar 14, 2022
37dbdd3
update codec
stevemurr Mar 14, 2022
50b80c0
update codec method
stevemurr Mar 14, 2022
e938174
add decoder
stevemurr Mar 14, 2022
1ca25b4
add context to gostdlib
stevemurr Mar 14, 2022
68e4e10
add mux namespace
stevemurr Mar 14, 2022
9465d96
update codec package with type alias
stevemurr Mar 14, 2022
a7dc276
session package update
stevemurr Mar 14, 2022
86bd684
make fields private
stevemurr Mar 14, 2022
5bfb92d
add I to interface declarations
stevemurr Mar 14, 2022
2cc2ed0
update interface naming
stevemurr Mar 14, 2022
9b3c06b
using partial class for package pattern
stevemurr Mar 14, 2022
85cc9c2
the partial class pattern for package extends life
stevemurr Mar 14, 2022
cee207a
update channel signatures
stevemurr Mar 14, 2022
58ea363
partial channel impl
stevemurr Mar 14, 2022
0fd77d7
add interfaces and EOF to io
stevemurr Mar 20, 2022
f7c97cf
remove partial class experiment
stevemurr Mar 20, 2022
2f71705
move waiter interface and impl
stevemurr Mar 20, 2022
3b579c3
moved interface
stevemurr Mar 20, 2022
0232476
remove partial class interface
stevemurr Mar 20, 2022
ffee2fb
remove partial class experiment
stevemurr Mar 20, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
TODO
typescript/dist
demos/groktunnel/groktunnel
demos/groktunnel/groktunnel

**/*/bin
**/*/obj
**/*/.DS_Store
14 changes: 14 additions & 0 deletions csharp/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
build_qmux:
dotnet build ./qmux/qmux.csproj
build_gostdlib:
dotnet build ./gostdlib/gostdlib.csproj
build: build_qmux
test:
dotnet test ./qmux.tests/qmux.tests.csproj
test_gostdlib:
dotnet test ./gostdlib.tests/gostdlib.tests.csproj
clean_src:
dotnet clean ./qmux/qmux.csproj
clean_test:
dotnet clean ./qmux.tests/qmux.tests.csproj
clean: clean_src clean_test
34 changes: 34 additions & 0 deletions csharp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# qmux for C#

> WIP

## Setup

`qmux` for C# requires `dotnet`. Install `dotnet` manually or via package
manager using instructions below.

### Package Manager Installation

| Platform | Command |
| -------- | ---------------------------- |
| macos | `brew install dotnet --cask` |
| win11 | `choco install dotnet` |
| win11 | `winget install dotnet` |
| apt | `apt install dotnet` |

### Manual Installation

Download the `dotnet` installer
[for your platform here](https://dotnet.microsoft.com/en-us/download).

## Build

```bash
dotnet build ./qmux/qmux.csproj
```

## Run tests

```bash
dotnet test ./qmux.tests/qmux.tests.csproj
```
27 changes: 27 additions & 0 deletions csharp/gostdlib.tests/gostdlib.tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\gostdlib\gostdlib.csproj" />
</ItemGroup>

</Project>
Empty file added csharp/gostdlib.tests/io/io.cs
Empty file.
3 changes: 3 additions & 0 deletions csharp/gostdlib/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# go

Go types used in the qmux csharp implementation.
97 changes: 97 additions & 0 deletions csharp/gostdlib/context/context.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
namespace gostdlib.context;

public interface IContext
{
// Deadline returns the time when work done on behalf of this context
// should be canceled. Deadline returns ok==false when no deadline is
// set. Successive calls to Deadline return the same results.
public (string, bool) Deadline();

// Done returns a channel that's closed when work done on behalf of this
// context should be canceled. Done may return nil if this context can
// never be canceled. Successive calls to Done return the same value.
// The close of the Done channel may happen asynchronously,
// after the cancel function returns.
//
// WithCancel arranges for Done to be closed when cancel is called;
// WithDeadline arranges for Done to be closed when the deadline
// expires; WithTimeout arranges for Done to be closed when the timeout
// elapses.
//
// Done is provided for use in select statements:
//
// // Stream generates values with DoSomething and sends them to out
// // until DoSomething returns an error or ctx.Done is closed.
// func Stream(ctx context.Context, out chan<- Value) error {
// for {
// v, err := DoSomething(ctx)
// if err != nil {
// return err
// }
// select {
// case <-ctx.Done():
// return ctx.Err()
// case out <- v:
// }
// }
// }
//
// See https://blog.golang.org/pipelines for more examples of how to use
// a Done channel for cancellation.
// Done() < -chan struct{ }

// If Done is not yet closed, Err returns nil.
// If Done is closed, Err returns a non-nil error explaining why:
// Canceled if the context was canceled
// or DeadlineExceeded if the context's deadline passed.
// After Err returns a non-nil error, successive calls to Err return the same error.
// Err() error

// Value returns the value associated with this context for key, or nil
// if no value is associated with key. Successive calls to Value with
// the same key returns the same result.
//
// Use context values only for request-scoped data that transits
// processes and API boundaries, not for passing optional parameters to
// functions.
//
// A key identifies a specific value in a Context. Functions that wish
// to store values in Context typically allocate a key in a global
// variable then use that key as the argument to context.WithValue and
// Context.Value. A key can be any type that supports equality;
// packages should define keys as an unexported type to avoid
// collisions.
//
// Packages that define a Context key should provide type-safe accessors
// for the values stored using that key:
//
// // Package user defines a User type that's stored in Contexts.
// package user
//
// import "context"
//
// // User is the type of value stored in the Contexts.
// type User struct {...}
//
// // key is an unexported type for keys defined in this package.
// // This prevents collisions with keys defined in other packages.
// type key int
//
// // userKey is the key for user.User values in Contexts. It is
// // unexported; clients use user.NewContext and user.FromContext
// // instead of using this key directly.
// var userKey key
//
// // NewContext returns a new Context that carries value u.
// func NewContext(ctx context.Context, u *User) context.Context {
// return context.WithValue(ctx, userKey, u)
// }
//
// // FromContext returns the User value stored in ctx, if any.
// func FromContext(ctx context.Context) (*User, bool) {
// u, ok := ctx.Value(userKey).(*User)
// return u, ok
// }
// Value(key interface{ }) interface{ }
object Value(object key);
}
92 changes: 92 additions & 0 deletions csharp/gostdlib/errors/errors.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
namespace gostdlib.errors;

public static partial class errors
{
public class Error
{
private string errorString;

public Error(string errorString)
{
this.errorString = errorString;
}

public override string ToString()
{
return $"{this.errorString}";
}
}

// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package errors implements functions to manipulate errors.
//
// The New function creates errors whose only content is a text message.
//
// The Unwrap, Is and As functions work on errors that may wrap other errors.
// An error wraps another error if its type has the method
//
// Unwrap() error
//
// If e.Unwrap() returns a non-nil error w, then we say that e wraps w.
//
// Unwrap unpacks wrapped errors. If its argument's type has an
// Unwrap method, it calls the method once. Otherwise, it returns nil.
//
// A simple way to create wrapped errors is to call fmt.Errorf and apply the %w verb
// to the error argument:
//
// errors.Unwrap(fmt.Errorf("... %w ...", ..., err, ...))
//
// returns err.
//
// Is unwraps its first argument sequentially looking for an error that matches the
// second. It reports whether it finds a match. It should be used in preference to
// simple equality checks:
//
// if errors.Is(err, fs.ErrExist)
//
// is preferable to
//
// if err == fs.ErrExist
//
// because the former will succeed if err wraps fs.ErrExist.
//
// As unwraps its first argument sequentially looking for an error that can be
// assigned to its second argument, which must be a pointer. If it succeeds, it
// performs the assignment and returns true. Otherwise, it returns false. The form
//
// var perr *fs.PathError
// if errors.As(err, &perr) {
// fmt.Println(perr.Path)
// }
//
// is preferable to
//
// if perr, ok := err.(*fs.PathError); ok {
// fmt.Println(perr.Path)
// }
//
// because the former will succeed if err wraps an *fs.PathError.
// package errors

// New returns an error that formats as the given text.
// Each call to New returns a distinct error value even if the text is identical.

// func New(text string) error {
// return &errorString{text}
// }

// // errorString is a trivial implementation of error.
// type errorString struct {

// s string
// }

// func(e * errorString) Error() string
// {
// return e.s
// }
}
9 changes: 9 additions & 0 deletions csharp/gostdlib/gostdlib.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
23 changes: 23 additions & 0 deletions csharp/gostdlib/io/io.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace gostdlib.io;
using gostdlib.errors;
public static partial class io
{
public interface IWriteCloser : IWriter, ICloser { }
public interface IReadCloser : IReader, ICloser { }
public interface IWriter
{
public int Write(byte[] p);
}

public interface IReader
{
public (int, errors.Error?) Read(byte[] p);
}

public interface ICloser
{
public void Close();
}

public static errors.Error EOF = new errors.Error("EOF");
}
22 changes: 22 additions & 0 deletions csharp/qmux.tests/codec/message_close_test.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace qmux.tests.codec;

using Xunit;

using qmux.codec;

public class TestCloseMessage
{
[Fact]
public void Test_CloseMessage_MarshalUnmarshalMuxRoundtrip()
{
var msg1 = new codec.CloseMessage()
{
ChannelId = 10,
};

var marshaled = msg1.MarshalMux();
var msg2 = new codec.CloseMessage();
msg2.UnmarshalMux(marshaled);
Assert.Equal(msg1.ChannelId, msg2.ChannelId);
}
}
26 changes: 26 additions & 0 deletions csharp/qmux.tests/codec/message_data_test.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
namespace qmux.tests.codec;

using Xunit;

using qmux.codec;

public class TestDataMessage
{
[Fact]
public void Test_DataMessage_MarshalUnmarshalMuxRoundtrip()
{
var msg1 = new codec.DataMessage()
{
ChannelId = 10,
Length = 5,
Data = new byte[5] { 0x20, 0x20, 0x20, 0x20, 0x20 },
};

var marshaled = msg1.MarshalMux();
var msg2 = new codec.DataMessage();
msg2.UnmarshalMux(marshaled);
Assert.Equal(msg1.ChannelId, msg2.ChannelId);
Assert.Equal(msg1.Length, msg2.Length);
Assert.Equal(msg1.Data, msg2.Data);
}
}
22 changes: 22 additions & 0 deletions csharp/qmux.tests/codec/message_eof_test.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace qmux.tests.codec;

using Xunit;

using qmux.codec;

public class TestEofMessage
{
[Fact]
public void Test_EofMessage_MarshalUnmarshalMuxRoundtrip()
{
var msg1 = new codec.EofMessage()
{
ChannelId = 10,
};

var marshaled = msg1.MarshalMux();
var msg2 = new codec.EofMessage();
msg2.UnmarshalMux(marshaled);
Assert.Equal(msg1.ChannelId, msg2.ChannelId);
}
}
Loading