Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
neoppod
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Levin Zimmermann
neoppod
Commits
c1e40bfe
Commit
c1e40bfe
authored
Jun 02, 2017
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
04b2b074
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
70 additions
and
37 deletions
+70
-37
go/xcommon/pipenet/pipenet.go
go/xcommon/pipenet/pipenet.go
+70
-37
No files found.
go/xcommon/pipenet/pipenet.go
View file @
c1e40bfe
...
...
@@ -46,7 +46,7 @@ var (
// 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 ?
addr
string
//
port + c/s depending on connection endpoint
}
// Network implements synchronous in-memory network of pipes
...
...
@@ -95,6 +95,27 @@ type listener struct {
}
// allocFreeEntry finds first free port and allocate network entry for it
// must be called under .mu held
func
(
n
*
Network
)
allocFreeEntry
()
*
entry
{
// find first free port if it was not specified
port
:=
0
for
;
port
<
len
(
n
.
entryv
);
port
++
{
if
n
.
entryv
[
port
]
==
nil
{
break
}
}
// if all busy it exits with port == len(n.entryv)
// grow if needed
for
port
>=
len
(
n
.
entryv
)
{
n
.
entryv
=
append
(
n
.
entryv
,
nil
)
}
e
:=
&
entry
{
network
:
n
,
port
:
port
}
n
.
entryv
[
port
]
=
e
return
e
}
// empty checks whether both 2 pipe endpoints and listener are nil
func
(
e
*
entry
)
empty
()
bool
{
...
...
@@ -111,7 +132,30 @@ func (a *Addr) String() string { return a.addr } // XXX Network() + ":" + a.addr
func
(
n
*
Network
)
netname
()
string
{
return
NetPrefix
+
n
.
Name
}
// Close closes the listener
// it interrupts all currently in-flight calls to Accept
func
(
l
*
listener
)
Close
()
error
{
l
.
closeOnce
.
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
}
// Listen starts new listener
// Ct either allocates new port if laddr is "" or binds to laddr.
// Once listener is started Dials could connect to listener address.
// Connection requests created by Dials could be accepted via Accept.
func
(
n
*
Network
)
Listen
(
laddr
string
)
(
net
.
Listener
,
error
)
{
lerr
:=
func
(
err
error
)
error
{
return
&
net
.
OpError
{
Op
:
"listen"
,
Net
:
n
.
netname
(),
Addr
:
&
Addr
{
n
.
netname
(),
laddr
},
Err
:
err
}
...
...
@@ -129,69 +173,58 @@ func (n *Network) Listen(laddr string) (net.Listener, error) {
n
.
mu
.
Lock
()
defer
n
.
mu
.
Unlock
()
var
e
*
entry
// find first free port if it was not specified
if
port
<
0
{
for
port
=
0
;
port
<
len
(
n
.
entryv
);
port
++
{
if
n
.
entryv
[
port
]
==
nil
{
break
}
e
=
n
.
allocFreeEntry
()
// else we check whether address is already used and if not allocate entry in-place
}
else
{
// grow if needed
for
port
>=
len
(
n
.
entryv
)
{
n
.
entryv
=
append
(
n
.
entryv
,
nil
)
}
// if all busy it exits with port == len(n.entryv)
}
// grow if needed
for
port
>=
len
(
n
.
entryv
)
{
n
.
entryv
=
append
(
n
.
entryv
,
nil
)
}
if
n
.
entryv
[
port
]
!=
nil
{
return
nil
,
lerr
(
errAddrAlreadyUsed
)
}
if
n
.
entryv
[
port
]
!=
nil
{
return
nil
,
lerr
(
errAddrAlreadyUsed
)
e
=
&
entry
{
network
:
n
,
port
:
port
}
n
.
entryv
[
port
]
=
e
}
e
:=
&
entry
{
network
:
n
,
port
:
port
}
// create listener under entry
l
:=
&
listener
{
entry
:
e
,
dialq
:
make
(
chan
chan
net
.
Conn
),
down
:
make
(
chan
struct
{}),
}
e
.
listener
=
l
n
.
entryv
[
port
]
=
e
return
l
,
nil
}
// Close closes the listener
// it interrupts all currently in-flight calls to Accept
func
(
l
*
listener
)
Close
()
error
{
l
.
closeOnce
.
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
}
// Accept tries to connect to Dial called with addr corresponding to our listener
func
(
l
*
listener
)
Accept
()
(
net
.
Conn
,
error
)
{
n
:=
l
.
entry
.
network
select
{
case
<-
l
.
down
:
return
nil
,
&
net
.
OpError
{
Op
:
"accept"
,
Net
:
l
.
entry
.
network
.
netname
(),
Addr
:
l
.
Addr
(),
Err
:
errNetClosed
}
return
nil
,
&
net
.
OpError
{
Op
:
"accept"
,
Net
:
n
.
netname
(),
Addr
:
l
.
Addr
(),
Err
:
errNetClosed
}
case
resp
:=
<-
l
.
dialq
:
// someone dialed us - let's connect
pc
,
ps
:=
net
.
Pipe
()
// XXX allocate port and register to l.network.pipev
// allocate entry and register conns to Network under it
n
.
mu
.
Lock
()
e
:=
n
.
allocFreeEntry
()
e
.
pipev
[
0
]
=
&
conn
{
entry
:
e
,
endpoint
:
0
,
Conn
:
pc
}
e
.
pipev
[
1
]
=
&
conn
{
entry
:
e
,
endpoint
:
1
,
Conn
:
ps
}
n
.
mu
.
Unlock
()
resp
<-
pc
return
ps
,
nil
...
...
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