Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
neo
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
2
Merge Requests
2
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
Kirill Smelkov
neo
Commits
b1e8b102
Commit
b1e8b102
authored
Jun 02, 2017
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
0fa03444
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
96 additions
and
51 deletions
+96
-51
go/xcommon/pipenet/pipenet.go
go/xcommon/pipenet/pipenet.go
+96
-51
No files found.
go/xcommon/pipenet/pipenet.go
View file @
b1e8b102
...
...
@@ -15,7 +15,7 @@
//
// See COPYING file for full licensing terms.
// Package pipenet provides in-memory network of net.Pipes
// Package pipenet provides
synchronous
in-memory network of net.Pipes
//
// TODO describe addressing scheme
//
...
...
@@ -36,38 +36,69 @@ const NetPrefix = "pipe" // pipenet package works only with "pipe*" networks
var
(
errBadNetwork
=
errors
.
New
(
"pipenet: invalid network"
)
errBadAddress
=
errors
.
New
(
"
pipenet:
invalid address"
)
errBadAddress
=
errors
.
New
(
"invalid address"
)
errNetNotFound
=
errors
.
New
(
"no such network"
)
errNetClosed
=
errors
.
New
(
"network connection closed"
)
errAddrAlreadyUsed
=
errors
.
New
(
"address already in use"
)
errConnRefused
=
errors
.
New
(
"connection refused"
)
)
// Addr represents address of a pipenet endpoint
type
Addr
struct
{
network
string
// full network name, e.g. "pipe"
addr
string
// XXX -> port ? + including c/s ?
}
// Network
represents network of in-memory
pipes
// Network
implements synchronous in-memory network of
pipes
// It can be worked with the same way a regular TCP network is handled with Dial/Listen/Accept/...
//
// Network must be created with New
type
Network
struct
{
// name of this network under "pipe" namespace -> e.g. ""
// full network name will be reported as "pipe"+Name
// full network name will be reported as "pipe"+Name
XXX -> just full name ?
Name
string
mu
sync
.
Mutex
pipev
[]
*
pipe
// port -> listener + net.Pipe (?)
// listenv []chan dialReq // listener[port] is waiting here if != nil
entryv
[]
*
entry
// port -> listener | (conn, conn)
}
// pipe represents one pipenet connection XXX naming
// it can be either already connected (2 endpoints) or only listening (1 endpoint) XXX
type
pipe
struct
{
listener
*
listener
// listener is waiting here if != nil
// entry represents one Network entry
// it can be either already connected (2 endpoints) or only listening (1 endpoint)
// anything from the above becomes nil when closed
type
entry
struct
{
network
*
Network
port
int
pipev
[
2
]
*
conn
// connection endpoints are there if != nil
listener
*
listener
// listener is waiting here if != nil
}
// Addr represents address of a pipenet endpoint
type
Addr
struct
{
network
string
// full network name, e.g. "pipe"
addr
string
// XXX -> port ? + including c/s ?
// conn represents one endpoint of connection created under Network
type
conn
struct
{
entry
*
entry
endpoint
int
// 0 | 1 -> entry.pipev
net
.
Conn
closeOnce
sync
.
Once
}
// listener implements net.Listener for piped network
type
listener
struct
{
// network/port we are listening on
entry
*
entry
dialq
chan
chan
net
.
Conn
// Dial requests to our port go here
down
chan
struct
{}
// Close -> down=ready
closeOnce
sync
.
Once
}
// empty checks whether both 2 pipe endpoints and listener are nil
func
(
e
*
entry
)
empty
()
bool
{
return
e
.
pipev
[
0
]
==
nil
&&
e
.
pipev
[
1
]
==
nil
&&
e
.
listener
==
nil
}
func
(
a
*
Addr
)
Network
()
string
{
return
a
.
network
}
...
...
@@ -75,8 +106,6 @@ func (a *Addr) String() string { return a.addr } // XXX Network() + ":" + a.addr
func
(
n
*
Network
)
netname
()
string
{
return
NetPrefix
+
n
.
Name
}
// XXX do we need Conn wrapping net.Pipe ? (e.g. to override String())
func
(
n
*
Network
)
Listen
(
laddr
string
)
(
net
.
Listener
,
error
)
{
lerr
:=
func
(
err
error
)
error
{
...
...
@@ -97,50 +126,51 @@ func (n *Network) Listen(laddr string) (net.Listener, error) {
// find first free port if it was not specified
if
port
<
0
{
for
port
=
0
;
port
<
len
(
n
.
pipe
v
);
port
++
{
if
n
.
pipe
v
[
port
]
==
nil
{
for
port
=
0
;
port
<
len
(
n
.
entry
v
);
port
++
{
if
n
.
entry
v
[
port
]
==
nil
{
break
}
}
// if all busy it exits with port == len(n.
pipe
v)
// if all busy it exits with port == len(n.
entry
v)
}
// grow if needed
for
port
>=
len
(
n
.
pipe
v
)
{
n
.
pipev
=
append
(
n
.
pipe
v
,
nil
)
for
port
>=
len
(
n
.
entry
v
)
{
n
.
entryv
=
append
(
n
.
entry
v
,
nil
)
}
if
n
.
pipe
v
[
port
]
!=
nil
{
if
n
.
entry
v
[
port
]
!=
nil
{
return
nil
,
lerr
(
errAddrAlreadyUsed
)
}
e
:=
&
entry
{
network
:
n
,
port
:
port
}
l
:=
&
listener
{
network
:
n
,
port
:
port
,
entry
:
e
,
dialq
:
make
(
chan
chan
net
.
Conn
),
down
:
make
(
chan
struct
{}),
}
n
.
pipev
[
port
]
=
&
pipe
{
listener
:
l
}
e
.
listener
=
l
n
.
entryv
[
port
]
=
e
return
l
,
nil
}
// listener implements net.Listener for piped network
type
listener
struct
{
// network/port we are listening on
network
*
Network
port
int
dialq
chan
chan
net
.
Conn
// Dial requests to our port go here
down
chan
struct
{}
// Close -> down=ready
downOnce
sync
.
Once
// so Close several times is ok
}
// Close closes the listener
// it interrupts all currently in-flight calls to Accept
func
(
l
*
listener
)
Close
()
error
{
l
.
down
Once
.
Do
(
func
()
{
l
.
close
Once
.
Do
(
func
()
{
close
(
l
.
down
)
e
:=
l
.
entry
n
:=
e
.
network
n
.
mu
.
Lock
()
defer
n
.
mu
.
Unlock
()
e
.
listener
=
nil
if
e
.
empty
()
{
n
.
entryv
[
e
.
port
]
=
nil
}
})
return
nil
}
...
...
@@ -149,7 +179,7 @@ func (l *listener) Close() error {
func
(
l
*
listener
)
Accept
()
(
net
.
Conn
,
error
)
{
select
{
case
<-
l
.
down
:
return
nil
,
&
net
.
OpError
{
Op
:
"accept"
,
Net
:
l
.
network
.
netname
(),
Addr
:
l
.
Addr
(),
Err
:
errNetClosed
}
return
nil
,
&
net
.
OpError
{
Op
:
"accept"
,
Net
:
l
.
entry
.
network
.
netname
(),
Addr
:
l
.
Addr
(),
Err
:
errNetClosed
}
case
resp
:=
<-
l
.
dialq
:
// someone dialed us - let's connect
...
...
@@ -177,15 +207,15 @@ func (n *Network) Dial(addr string) (net.Conn, error) {
n
.
mu
.
Lock
()
defer
n
.
mu
.
Unlock
()
// XXX ok to defer here?
if
port
>=
len
(
n
.
pipe
v
)
{
if
port
>=
len
(
n
.
entry
v
)
{
return
nil
,
derr
(
errConnRefused
)
// XXX merge with vvv
}
p
:=
n
.
pipe
v
[
port
]
if
p
==
nil
||
p
.
listener
==
nil
{
e
:=
n
.
entry
v
[
port
]
if
e
==
nil
||
e
.
listener
==
nil
{
return
nil
,
derr
(
errConnRefused
)
// XXX merge with ^^^
}
l
:=
p
.
listener
l
:=
e
.
listener
// NOTE listener is not locking n.mu -> it is ok to send/receive under mu - FIXME not correct
// FIXME -> Accept needs to register new connection under n.mu
...
...
@@ -201,22 +231,37 @@ func (n *Network) Dial(addr string) (net.Conn, error) {
// Addr returns address where listener is accepting incoming connections
func
(
l
*
listener
)
Addr
()
net
.
Addr
{
return
&
Addr
{
network
:
l
.
network
.
netname
(),
addr
:
fmt
.
Sprintf
(
"%d"
,
l
.
port
)}
// NOTE no c/s XXX -> +l ?
e
:=
l
.
entry
n
:=
e
.
network
return
&
Addr
{
network
:
n
.
netname
(),
addr
:
fmt
.
Sprintf
(
"%d"
,
e
.
port
)}
// NOTE no c/s XXX -> +l ?
}
// XXX conn.Close - unregister from network.connv
// XXX conn.LocalAddr -> ...
// XXX conn.RemoteAddr -> ...
func
(
c
*
conn
)
Close
()
(
err
error
)
{
c
.
closeOnce
.
Do
(
func
()
{
err
=
c
.
Conn
.
Close
()
e
:=
c
.
entry
n
:=
e
.
network
// conn represents one endpoint of connection created under Network
type
conn
struct
{
network
*
Network
// XXX port + c/s ?
n
.
mu
.
Lock
()
defer
n
.
mu
.
Unlock
()
net
.
Conn
e
.
pipev
[
c
.
endpoint
]
=
nil
if
e
.
empty
()
{
n
.
entryv
[
e
.
port
]
=
nil
}
})
return
err
}
// XXX conn.Close - unregister from network.connv
// XXX conn.LocalAddr -> ...
// XXX conn.RemoteAddr -> ...
// ----------------------------------------
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment