Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
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
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
0e7995c0
Commit
0e7995c0
authored
Feb 23, 2011
by
Alex Brainman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
net: refactor windows code
R=golang-dev, rsc CC=golang-dev
https://golang.org/cl/4185054
parent
0cf6f8c0
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
310 additions
and
368 deletions
+310
-368
src/pkg/net/fd_windows.go
src/pkg/net/fd_windows.go
+309
-348
src/pkg/syscall/syscall_windows.go
src/pkg/syscall/syscall_windows.go
+0
-20
src/pkg/syscall/ztypes_windows_386.go
src/pkg/syscall/ztypes_windows_386.go
+1
-0
No files found.
src/pkg/net/fd_windows.go
View file @
0e7995c0
...
...
@@ -13,147 +13,241 @@ import (
"unsafe"
)
type
InvalidConnError
struct
{}
func
(
e
*
InvalidConnError
)
String
()
string
{
return
"invalid net.Conn"
}
func
(
e
*
InvalidConnError
)
Temporary
()
bool
{
return
false
}
func
(
e
*
InvalidConnError
)
Timeout
()
bool
{
return
false
}
var
initErr
os
.
Error
func
init
()
{
var
d
syscall
.
WSAData
e
:=
syscall
.
WSAStartup
(
uint32
(
0x101
),
&
d
)
if
e
!=
0
{
initErr
=
os
.
NewSyscallError
(
"WSAStartup"
,
e
)
}
}
func
closesocket
(
s
int
)
(
errno
int
)
{
return
syscall
.
Closesocket
(
int32
(
s
))
}
// Interface for all io operations.
type
anOpIface
interface
{
Op
()
*
anOp
Name
()
string
Submit
()
(
errno
int
)
}
// IO completion result parameters.
type
ioResult
struct
{
key
uint32
qty
uint32
errno
int
qty
uint32
err
int
}
// Network file descriptor.
type
netFD
struct
{
// locking/lifetime of sysfd
sysmu
sync
.
Mutex
sysref
int
closing
bool
// anOp implements functionality common to all io operations.
type
anOp
struct
{
// Used by IOCP interface, it must be first field
// of the struct, as our code rely on it.
o
syscall
.
Overlapped
// immutable until Close
sysfd
int
family
int
proto
int
cr
chan
*
ioResult
cw
chan
*
ioResult
net
string
laddr
Addr
raddr
Addr
resultc
chan
ioResult
// io completion results
errnoc
chan
int
// io submit / cancel operation errors
fd
*
netFD
}
// owned by client
rdeadline_delta
int64
rdeadline
int64
rio
sync
.
Mutex
wdeadline_delta
int64
wdeadline
int64
wio
sync
.
Mutex
func
(
o
*
anOp
)
Init
(
fd
*
netFD
)
{
o
.
fd
=
fd
o
.
resultc
=
make
(
chan
ioResult
,
1
)
o
.
errnoc
=
make
(
chan
int
)
}
type
InvalidConnError
struct
{}
func
(
o
*
anOp
)
Op
()
*
anOp
{
return
o
}
func
(
e
*
InvalidConnError
)
String
()
string
{
return
"invalid net.Conn"
}
func
(
e
*
InvalidConnError
)
Temporary
()
bool
{
return
false
}
func
(
e
*
InvalidConnError
)
Timeout
()
bool
{
return
false
}
// bufOp is used by io operations that read / write
// data from / to client buffer.
type
bufOp
struct
{
anOp
buf
syscall
.
WSABuf
}
// pollServer will run around waiting for io completion request
// to arrive. Every request received will contain channel to signal
// io owner about the completion.
func
(
o
*
bufOp
)
Init
(
fd
*
netFD
,
buf
[]
byte
)
{
o
.
anOp
.
Init
(
fd
)
o
.
buf
.
Len
=
uint32
(
len
(
buf
))
if
len
(
buf
)
==
0
{
o
.
buf
.
Buf
=
nil
}
else
{
o
.
buf
.
Buf
=
(
*
byte
)(
unsafe
.
Pointer
(
&
buf
[
0
]))
}
}
type
pollServer
struct
{
// resultSrv will retreive all io completion results from
// iocp and send them to the correspondent waiting client
// goroutine via channel supplied in the request.
type
resultSrv
struct
{
iocp
int32
}
func
newPollServer
()
(
s
*
pollServer
,
err
os
.
Error
)
{
s
=
new
(
pollServer
)
var
e
int
if
s
.
iocp
,
e
=
syscall
.
CreateIoCompletionPort
(
-
1
,
0
,
0
,
1
);
e
!=
0
{
return
nil
,
os
.
NewSyscallError
(
"CreateIoCompletionPort"
,
e
)
func
(
s
*
resultSrv
)
Run
()
{
var
o
*
syscall
.
Overlapped
var
key
uint32
var
r
ioResult
for
{
r
.
err
=
syscall
.
GetQueuedCompletionStatus
(
s
.
iocp
,
&
(
r
.
qty
),
&
key
,
&
o
,
syscall
.
INFINITE
)
switch
{
case
r
.
err
==
0
:
// Dequeued successfully completed io packet.
case
r
.
err
==
syscall
.
WAIT_TIMEOUT
&&
o
==
nil
:
// Wait has timed out (should not happen now, but might be used in the future).
panic
(
"GetQueuedCompletionStatus timed out"
)
case
o
==
nil
:
// Failed to dequeue anything -> report the error.
panic
(
"GetQueuedCompletionStatus failed "
+
syscall
.
Errstr
(
r
.
err
))
default
:
// Dequeued failed io packet.
}
(
*
anOp
)(
unsafe
.
Pointer
(
o
))
.
resultc
<-
r
}
go
s
.
Run
()
return
s
,
nil
}
type
ioPacket
struct
{
// Used by IOCP interface,
// it must be first field of the struct,
// as our code rely on it.
o
syscall
.
Overlapped
// Link to the io owner
.
c
chan
*
ioResult
w
*
syscall
.
WSABuf
// ioSrv executes net io requests
.
type
ioSrv
struct
{
submchan
chan
anOpIface
// submit io requests
canchan
chan
anOpIface
// cancel io requests
}
func
(
s
*
pollServer
)
getCompletedIO
()
(
ov
*
syscall
.
Overlapped
,
result
*
ioResult
,
err
os
.
Error
)
{
var
r
ioResult
var
o
*
syscall
.
Overlapped
e
:=
syscall
.
GetQueuedCompletionStatus
(
s
.
iocp
,
&
r
.
qty
,
&
r
.
key
,
&
o
,
syscall
.
INFINITE
)
switch
{
case
e
==
0
:
// Dequeued successfully completed io packet.
return
o
,
&
r
,
nil
case
e
==
syscall
.
WAIT_TIMEOUT
&&
o
==
nil
:
// Wait has timed out (should not happen now, but might be used in the future).
return
nil
,
&
r
,
os
.
NewSyscallError
(
"GetQueuedCompletionStatus"
,
e
)
case
o
==
nil
:
// Failed to dequeue anything -> report the error.
return
nil
,
&
r
,
os
.
NewSyscallError
(
"GetQueuedCompletionStatus"
,
e
)
default
:
// Dequeued failed io packet.
r
.
errno
=
e
return
o
,
&
r
,
nil
// ProcessRemoteIO will execute submit io requests on behalf
// of other goroutines, all on a single os thread, so it can
// cancel them later. Results of all operations will be sent
// back to their requesters via channel supplied in request.
func
(
s
*
ioSrv
)
ProcessRemoteIO
()
{
runtime
.
LockOSThread
()
defer
runtime
.
UnlockOSThread
()
for
{
select
{
case
o
:=
<-
s
.
submchan
:
o
.
Op
()
.
errnoc
<-
o
.
Submit
()
case
o
:=
<-
s
.
canchan
:
o
.
Op
()
.
errnoc
<-
syscall
.
CancelIo
(
uint32
(
o
.
Op
()
.
fd
.
sysfd
))
}
}
return
}
func
(
s
*
pollServer
)
Run
()
{
for
{
o
,
r
,
err
:=
s
.
getCompletedIO
()
if
err
!=
nil
{
panic
(
"Run pollServer: "
+
err
.
String
()
+
"
\n
"
)
// ExecIO executes a single io operation. It either executes it
// inline, or, if timeouts are employed, passes the request onto
// a special goroutine and waits for completion or cancels request.
func
(
s
*
ioSrv
)
ExecIO
(
oi
anOpIface
,
deadline_delta
int64
)
(
n
int
,
err
os
.
Error
)
{
var
e
int
o
:=
oi
.
Op
()
if
deadline_delta
>
0
{
// Send request to a special dedicated thread,
// so it can stop the io with CancelIO later.
s
.
submchan
<-
oi
e
=
<-
o
.
errnoc
}
else
{
e
=
oi
.
Submit
()
}
switch
e
{
case
0
:
// IO completed immediately, but we need to get our completion message anyway.
case
syscall
.
ERROR_IO_PENDING
:
// IO started, and we have to wait for it's completion.
default
:
return
0
,
&
OpError
{
oi
.
Name
(),
o
.
fd
.
net
,
o
.
fd
.
laddr
,
os
.
Errno
(
e
)}
}
// Wait for our request to complete.
var
r
ioResult
if
deadline_delta
>
0
{
select
{
case
r
=
<-
o
.
resultc
:
case
<-
time
.
After
(
deadline_delta
)
:
s
.
canchan
<-
oi
<-
o
.
errnoc
r
=
<-
o
.
resultc
if
r
.
err
==
syscall
.
ERROR_OPERATION_ABORTED
{
// IO Canceled
r
.
err
=
syscall
.
EWOULDBLOCK
}
}
p
:=
(
*
ioPacket
)(
unsafe
.
Pointer
(
o
))
p
.
c
<-
r
}
else
{
r
=
<-
o
.
resultc
}
if
r
.
err
!=
0
{
err
=
&
OpError
{
oi
.
Name
(),
o
.
fd
.
net
,
o
.
fd
.
laddr
,
os
.
Errno
(
r
.
err
)}
}
return
int
(
r
.
qty
),
err
}
// Network FD methods.
// All the network FDs use a single pollServer.
var
pollserver
*
pollServer
// Start helper goroutines.
var
resultsrv
*
resultSrv
var
iosrv
*
ioSrv
var
onceStartServer
sync
.
Once
func
startServer
()
{
p
,
err
:=
newPollServer
()
if
err
!=
nil
{
panic
(
"Start pollServer: "
+
err
.
String
()
+
"
\n
"
)
}
pollserver
=
p
go
timeoutIO
()
resultsrv
=
new
(
resultSrv
)
var
errno
int
resultsrv
.
iocp
,
errno
=
syscall
.
CreateIoCompletionPort
(
-
1
,
0
,
0
,
1
)
if
errno
!=
0
{
panic
(
"CreateIoCompletionPort failed "
+
syscall
.
Errstr
(
errno
))
}
go
resultsrv
.
Run
()
iosrv
=
new
(
ioSrv
)
iosrv
.
submchan
=
make
(
chan
anOpIface
)
iosrv
.
canchan
=
make
(
chan
anOpIface
)
go
iosrv
.
ProcessRemoteIO
()
}
var
initErr
os
.
Error
// Network file descriptor.
type
netFD
struct
{
// locking/lifetime of sysfd
sysmu
sync
.
Mutex
sysref
int
closing
bool
func
newFD
(
fd
,
family
,
proto
int
,
net
string
,
laddr
,
raddr
Addr
)
(
f
*
netFD
,
err
os
.
Error
)
{
if
initErr
!=
nil
{
return
nil
,
initErr
}
onceStartServer
.
Do
(
startServer
)
// Associate our socket with pollserver.iocp.
if
_
,
e
:=
syscall
.
CreateIoCompletionPort
(
int32
(
fd
),
pollserver
.
iocp
,
0
,
0
);
e
!=
0
{
return
nil
,
&
OpError
{
"CreateIoCompletionPort"
,
net
,
laddr
,
os
.
Errno
(
e
)}
}
// immutable until Close
sysfd
int
family
int
proto
int
net
string
laddr
Addr
raddr
Addr
// owned by client
rdeadline_delta
int64
rdeadline
int64
rio
sync
.
Mutex
wdeadline_delta
int64
wdeadline
int64
wio
sync
.
Mutex
}
func
allocFD
(
fd
,
family
,
proto
int
,
net
string
,
laddr
,
raddr
Addr
)
(
f
*
netFD
)
{
f
=
&
netFD
{
sysfd
:
fd
,
family
:
family
,
proto
:
proto
,
cr
:
make
(
chan
*
ioResult
,
1
),
cw
:
make
(
chan
*
ioResult
,
1
),
net
:
net
,
laddr
:
laddr
,
raddr
:
raddr
,
}
runtime
.
SetFinalizer
(
f
,
(
*
netFD
)
.
Close
)
return
f
,
nil
return
f
}
func
newFD
(
fd
,
family
,
proto
int
,
net
string
,
laddr
,
raddr
Addr
)
(
f
*
netFD
,
err
os
.
Error
)
{
if
initErr
!=
nil
{
return
nil
,
initErr
}
onceStartServer
.
Do
(
startServer
)
// Associate our socket with resultsrv.iocp.
if
_
,
e
:=
syscall
.
CreateIoCompletionPort
(
int32
(
fd
),
resultsrv
.
iocp
,
0
,
0
);
e
!=
0
{
return
nil
,
&
OpError
{
"CreateIoCompletionPort"
,
net
,
laddr
,
os
.
Errno
(
e
)}
}
return
allocFD
(
fd
,
family
,
proto
,
net
,
laddr
,
raddr
),
nil
}
// Add a reference to this fd.
...
...
@@ -172,7 +266,7 @@ func (fd *netFD) decref() {
// In case the user has set linger, switch to blocking mode so
// the close blocks. As long as this doesn't happen often, we
// can handle the extra OS processes. Otherwise we'll need to
// use the
pollserver
for Close too. Sigh.
// use the
resultsrv
for Close too. Sigh.
syscall
.
SetNonblock
(
fd
.
sysfd
,
false
)
closesocket
(
fd
.
sysfd
)
fd
.
sysfd
=
-
1
...
...
@@ -194,89 +288,22 @@ func (fd *netFD) Close() os.Error {
return
nil
}
func
newWSABuf
(
p
[]
byte
)
*
syscall
.
WSABuf
{
var
p0
*
byte
if
len
(
p
)
>
0
{
p0
=
(
*
byte
)(
unsafe
.
Pointer
(
&
p
[
0
]))
}
return
&
syscall
.
WSABuf
{
uint32
(
len
(
p
)),
p0
}
}
func
waitPacket
(
fd
*
netFD
,
pckt
*
ioPacket
,
mode
int
)
(
r
*
ioResult
)
{
var
delta
int64
if
mode
==
'r'
{
delta
=
fd
.
rdeadline_delta
}
if
mode
==
'w'
{
delta
=
fd
.
wdeadline_delta
}
if
delta
<=
0
{
return
<-
pckt
.
c
}
// Read from network.
select
{
case
r
=
<-
pckt
.
c
:
case
<-
time
.
After
(
delta
)
:
a
:=
&
arg
{
f
:
cancel
,
fd
:
fd
,
pckt
:
pckt
,
c
:
make
(
chan
int
)}
ioChan
<-
a
<-
a
.
c
r
=
<-
pckt
.
c
if
r
.
errno
==
995
{
// IO Canceled
r
.
errno
=
syscall
.
EWOULDBLOCK
}
}
return
r
type
readOp
struct
{
bufOp
}
const
(
read
=
iota
readfrom
write
writeto
cancel
)
func
(
o
*
readOp
)
Submit
()
(
errno
int
)
{
var
d
,
f
uint32
return
syscall
.
WSARecv
(
uint32
(
o
.
fd
.
sysfd
),
&
o
.
buf
,
1
,
&
d
,
&
f
,
&
o
.
o
,
nil
)
}
type
arg
struct
{
f
int
fd
*
netFD
pckt
*
ioPacket
done
*
uint32
flags
*
uint32
rsa
*
syscall
.
RawSockaddrAny
size
*
int32
sa
*
syscall
.
Sockaddr
c
chan
int
}
var
ioChan
chan
*
arg
=
make
(
chan
*
arg
)
func
timeoutIO
()
{
// CancelIO only cancels all pending input and output (I/O) operations that are
// issued by the calling thread for the specified file, does not cancel I/O
// operations that other threads issue for a file handle. So we need do all timeout
// I/O in single OS thread.
runtime
.
LockOSThread
()
defer
runtime
.
UnlockOSThread
()
for
{
o
:=
<-
ioChan
var
e
int
switch
o
.
f
{
case
read
:
e
=
syscall
.
WSARecv
(
uint32
(
o
.
fd
.
sysfd
),
o
.
pckt
.
w
,
1
,
o
.
done
,
o
.
flags
,
&
o
.
pckt
.
o
,
nil
)
case
readfrom
:
e
=
syscall
.
WSARecvFrom
(
uint32
(
o
.
fd
.
sysfd
),
o
.
pckt
.
w
,
1
,
o
.
done
,
o
.
flags
,
o
.
rsa
,
o
.
size
,
&
o
.
pckt
.
o
,
nil
)
case
write
:
e
=
syscall
.
WSASend
(
uint32
(
o
.
fd
.
sysfd
),
o
.
pckt
.
w
,
1
,
o
.
done
,
uint32
(
0
),
&
o
.
pckt
.
o
,
nil
)
case
writeto
:
e
=
syscall
.
WSASendto
(
uint32
(
o
.
fd
.
sysfd
),
o
.
pckt
.
w
,
1
,
o
.
done
,
0
,
*
o
.
sa
,
&
o
.
pckt
.
o
,
nil
)
case
cancel
:
e
=
syscall
.
CancelIo
(
uint32
(
o
.
fd
.
sysfd
))
}
o
.
c
<-
e
}
func
(
o
*
readOp
)
Name
()
string
{
return
"WSARecv"
}
func
(
fd
*
netFD
)
Read
(
p
[]
byte
)
(
n
int
,
err
os
.
Error
)
{
func
(
fd
*
netFD
)
Read
(
buf
[]
byte
)
(
n
int
,
err
os
.
Error
)
{
if
fd
==
nil
{
return
0
,
os
.
EINVAL
}
...
...
@@ -287,45 +314,37 @@ func (fd *netFD) Read(p []byte) (n int, err os.Error) {
if
fd
.
sysfd
==
-
1
{
return
0
,
os
.
EINVAL
}
// Submit receive request.
var
pckt
ioPacket
pckt
.
c
=
fd
.
cr
pckt
.
w
=
newWSABuf
(
p
)
var
done
uint32
flags
:=
uint32
(
0
)
var
e
int
if
fd
.
rdeadline_delta
>
0
{
a
:=
&
arg
{
f
:
read
,
fd
:
fd
,
pckt
:
&
pckt
,
done
:
&
done
,
flags
:
&
flags
,
c
:
make
(
chan
int
)}
ioChan
<-
a
e
=
<-
a
.
c
}
else
{
e
=
syscall
.
WSARecv
(
uint32
(
fd
.
sysfd
),
pckt
.
w
,
1
,
&
done
,
&
flags
,
&
pckt
.
o
,
nil
)
}
switch
e
{
case
0
:
// IO completed immediately, but we need to get our completion message anyway.
case
syscall
.
ERROR_IO_PENDING
:
// IO started, and we have to wait for it's completion.
default
:
return
0
,
&
OpError
{
"WSARecv"
,
fd
.
net
,
fd
.
laddr
,
os
.
Errno
(
e
)}
}
// Wait for our request to complete.
r
:=
waitPacket
(
fd
,
&
pckt
,
'r'
)
if
r
.
errno
!=
0
{
err
=
&
OpError
{
"WSARecv"
,
fd
.
net
,
fd
.
laddr
,
os
.
Errno
(
r
.
errno
)}
}
n
=
int
(
r
.
qty
)
var
o
readOp
o
.
Init
(
fd
,
buf
)
n
,
err
=
iosrv
.
ExecIO
(
&
o
,
fd
.
rdeadline_delta
)
if
err
==
nil
&&
n
==
0
{
err
=
os
.
EOF
err
=
&
OpError
{
o
.
Name
(),
o
.
fd
.
net
,
o
.
fd
.
laddr
,
os
.
EOF
}
}
return
}
func
(
fd
*
netFD
)
ReadFrom
(
p
[]
byte
)
(
n
int
,
sa
syscall
.
Sockaddr
,
err
os
.
Error
)
{
// ReadFrom from network.
type
readFromOp
struct
{
bufOp
rsa
syscall
.
RawSockaddrAny
}
func
(
o
*
readFromOp
)
Submit
()
(
errno
int
)
{
var
d
,
f
uint32
l
:=
int32
(
unsafe
.
Sizeof
(
o
.
rsa
))
return
syscall
.
WSARecvFrom
(
uint32
(
o
.
fd
.
sysfd
),
&
o
.
buf
,
1
,
&
d
,
&
f
,
&
o
.
rsa
,
&
l
,
&
o
.
o
,
nil
)
}
func
(
o
*
readFromOp
)
Name
()
string
{
return
"WSARecvFrom"
}
func
(
fd
*
netFD
)
ReadFrom
(
buf
[]
byte
)
(
n
int
,
sa
syscall
.
Sockaddr
,
err
os
.
Error
)
{
if
fd
==
nil
{
return
0
,
nil
,
os
.
EINVAL
}
if
len
(
p
)
==
0
{
if
len
(
buf
)
==
0
{
return
0
,
nil
,
nil
}
fd
.
rio
.
Lock
()
...
...
@@ -335,41 +354,29 @@ func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err os.Error) {
if
fd
.
sysfd
==
-
1
{
return
0
,
nil
,
os
.
EINVAL
}
// Submit receive request.
var
pckt
ioPacket
pckt
.
c
=
fd
.
cr
pckt
.
w
=
newWSABuf
(
p
)
var
done
uint32
flags
:=
uint32
(
0
)
var
rsa
syscall
.
RawSockaddrAny
l
:=
int32
(
unsafe
.
Sizeof
(
rsa
))
var
e
int
if
fd
.
rdeadline_delta
>
0
{
a
:=
&
arg
{
f
:
readfrom
,
fd
:
fd
,
pckt
:
&
pckt
,
done
:
&
done
,
flags
:
&
flags
,
rsa
:
&
rsa
,
size
:
&
l
,
c
:
make
(
chan
int
)}
ioChan
<-
a
e
=
<-
a
.
c
}
else
{
e
=
syscall
.
WSARecvFrom
(
uint32
(
fd
.
sysfd
),
pckt
.
w
,
1
,
&
done
,
&
flags
,
&
rsa
,
&
l
,
&
pckt
.
o
,
nil
)
}
switch
e
{
case
0
:
// IO completed immediately, but we need to get our completion message anyway.
case
syscall
.
ERROR_IO_PENDING
:
// IO started, and we have to wait for it's completion.
default
:
return
0
,
nil
,
&
OpError
{
"WSARecvFrom"
,
fd
.
net
,
fd
.
laddr
,
os
.
Errno
(
e
)}
}
// Wait for our request to complete.
r
:=
waitPacket
(
fd
,
&
pckt
,
'r'
)
if
r
.
errno
!=
0
{
err
=
&
OpError
{
"WSARecvFrom"
,
fd
.
net
,
fd
.
laddr
,
os
.
Errno
(
r
.
errno
)}
}
n
=
int
(
r
.
qty
)
sa
,
_
=
rsa
.
Sockaddr
()
var
o
readFromOp
o
.
Init
(
fd
,
buf
)
n
,
err
=
iosrv
.
ExecIO
(
&
o
,
fd
.
rdeadline_delta
)
sa
,
_
=
o
.
rsa
.
Sockaddr
()
return
}
func
(
fd
*
netFD
)
Write
(
p
[]
byte
)
(
n
int
,
err
os
.
Error
)
{
// Write to network.
type
writeOp
struct
{
bufOp
}
func
(
o
*
writeOp
)
Submit
()
(
errno
int
)
{
var
d
uint32
return
syscall
.
WSASend
(
uint32
(
o
.
fd
.
sysfd
),
&
o
.
buf
,
1
,
&
d
,
0
,
&
o
.
o
,
nil
)
}
func
(
o
*
writeOp
)
Name
()
string
{
return
"WSASend"
}
func
(
fd
*
netFD
)
Write
(
buf
[]
byte
)
(
n
int
,
err
os
.
Error
)
{
if
fd
==
nil
{
return
0
,
os
.
EINVAL
}
...
...
@@ -380,41 +387,32 @@ func (fd *netFD) Write(p []byte) (n int, err os.Error) {
if
fd
.
sysfd
==
-
1
{
return
0
,
os
.
EINVAL
}
// Submit send request.
var
pckt
ioPacket
pckt
.
c
=
fd
.
cw
pckt
.
w
=
newWSABuf
(
p
)
var
done
uint32
var
e
int
if
fd
.
wdeadline_delta
>
0
{
a
:=
&
arg
{
f
:
write
,
fd
:
fd
,
pckt
:
&
pckt
,
done
:
&
done
,
c
:
make
(
chan
int
)}
ioChan
<-
a
e
=
<-
a
.
c
}
else
{
e
=
syscall
.
WSASend
(
uint32
(
fd
.
sysfd
),
pckt
.
w
,
1
,
&
done
,
uint32
(
0
),
&
pckt
.
o
,
nil
)
}
switch
e
{
case
0
:
// IO completed immediately, but we need to get our completion message anyway.
case
syscall
.
ERROR_IO_PENDING
:
// IO started, and we have to wait for it's completion.
default
:
return
0
,
&
OpError
{
"WSASend"
,
fd
.
net
,
fd
.
laddr
,
os
.
Errno
(
e
)}
}
// Wait for our request to complete.
r
:=
waitPacket
(
fd
,
&
pckt
,
'w'
)
if
r
.
errno
!=
0
{
err
=
&
OpError
{
"WSASend"
,
fd
.
net
,
fd
.
laddr
,
os
.
Errno
(
r
.
errno
)}
}
n
=
int
(
r
.
qty
)
return
var
o
writeOp
o
.
Init
(
fd
,
buf
)
return
iosrv
.
ExecIO
(
&
o
,
fd
.
wdeadline_delta
)
}
// WriteTo to network.
type
writeToOp
struct
{
bufOp
sa
syscall
.
Sockaddr
}
func
(
o
*
writeToOp
)
Submit
()
(
errno
int
)
{
var
d
uint32
return
syscall
.
WSASendto
(
uint32
(
o
.
fd
.
sysfd
),
&
o
.
buf
,
1
,
&
d
,
0
,
o
.
sa
,
&
o
.
o
,
nil
)
}
func
(
o
*
writeToOp
)
Name
()
string
{
return
"WSASendto"
}
func
(
fd
*
netFD
)
WriteTo
(
p
[]
byte
,
sa
syscall
.
Sockaddr
)
(
n
int
,
err
os
.
Error
)
{
func
(
fd
*
netFD
)
WriteTo
(
buf
[]
byte
,
sa
syscall
.
Sockaddr
)
(
n
int
,
err
os
.
Error
)
{
if
fd
==
nil
{
return
0
,
os
.
EINVAL
}
if
len
(
p
)
==
0
{
if
len
(
buf
)
==
0
{
return
0
,
nil
}
fd
.
wio
.
Lock
()
...
...
@@ -424,34 +422,29 @@ func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err os.Error) {
if
fd
.
sysfd
==
-
1
{
return
0
,
os
.
EINVAL
}
// Submit send request.
var
pckt
ioPacket
pckt
.
c
=
fd
.
cw
pckt
.
w
=
newWSABuf
(
p
)
var
done
uint32
var
e
int
if
fd
.
wdeadline_delta
>
0
{
a
:=
&
arg
{
f
:
writeto
,
fd
:
fd
,
pckt
:
&
pckt
,
done
:
&
done
,
sa
:
&
sa
,
c
:
make
(
chan
int
)}
ioChan
<-
a
e
=
<-
a
.
c
}
else
{
e
=
syscall
.
WSASendto
(
uint32
(
fd
.
sysfd
),
pckt
.
w
,
1
,
&
done
,
0
,
sa
,
&
pckt
.
o
,
nil
)
}
switch
e
{
case
0
:
// IO completed immediately, but we need to get our completion message anyway.
case
syscall
.
ERROR_IO_PENDING
:
// IO started, and we have to wait for it's completion.
default
:
return
0
,
&
OpError
{
"WSASendTo"
,
fd
.
net
,
fd
.
laddr
,
os
.
Errno
(
e
)}
}
// Wait for our request to complete.
r
:=
waitPacket
(
fd
,
&
pckt
,
'w'
)
if
r
.
errno
!=
0
{
err
=
&
OpError
{
"WSASendTo"
,
fd
.
net
,
fd
.
laddr
,
os
.
Errno
(
r
.
errno
)}
}
n
=
int
(
r
.
qty
)
return
var
o
writeToOp
o
.
Init
(
fd
,
buf
)
o
.
sa
=
sa
return
iosrv
.
ExecIO
(
&
o
,
fd
.
wdeadline_delta
)
}
// Accept new network connections.
type
acceptOp
struct
{
anOp
newsock
int
attrs
[
2
]
syscall
.
RawSockaddrAny
// space for local and remote address only
}
func
(
o
*
acceptOp
)
Submit
()
(
errno
int
)
{
var
d
uint32
l
:=
uint32
(
unsafe
.
Sizeof
(
o
.
attrs
[
0
]))
return
syscall
.
AcceptEx
(
uint32
(
o
.
fd
.
sysfd
),
uint32
(
o
.
newsock
),
(
*
byte
)(
unsafe
.
Pointer
(
&
o
.
attrs
[
0
])),
0
,
l
,
l
,
&
d
,
&
o
.
o
)
}
func
(
o
*
acceptOp
)
Name
()
string
{
return
"AcceptEx"
}
func
(
fd
*
netFD
)
accept
(
toAddr
func
(
syscall
.
Sockaddr
)
Addr
)
(
nfd
*
netFD
,
err
os
.
Error
)
{
...
...
@@ -474,72 +467,40 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.
// Associate our new socket with IOCP.
onceStartServer
.
Do
(
startServer
)
if
_
,
e
=
syscall
.
CreateIoCompletionPort
(
int32
(
s
),
pollserver
.
iocp
,
0
,
0
);
e
!=
0
{
if
_
,
e
=
syscall
.
CreateIoCompletionPort
(
int32
(
s
),
resultsrv
.
iocp
,
0
,
0
);
e
!=
0
{
return
nil
,
&
OpError
{
"CreateIoCompletionPort"
,
fd
.
net
,
fd
.
laddr
,
os
.
Errno
(
e
)}
}
// Submit accept request.
// Will use new unique channel here, because, unlike Read or Write,
// Accept is expected to be executed by many goroutines simultaniously.
var
pckt
ioPacket
pckt
.
c
=
make
(
chan
*
ioResult
)
attrs
,
e
:=
syscall
.
AcceptIOCP
(
fd
.
sysfd
,
s
,
&
pckt
.
o
)
switch
e
{
case
0
:
// IO completed immediately, but we need to get our completion message anyway.
case
syscall
.
ERROR_IO_PENDING
:
// IO started, and we have to wait for it's completion.
default
:
closesocket
(
s
)
return
nil
,
&
OpError
{
"AcceptEx"
,
fd
.
net
,
fd
.
laddr
,
os
.
Errno
(
e
)}
}
// Wait for peer connection.
r
:=
<-
pckt
.
c
if
r
.
errno
!=
0
{
var
o
acceptOp
o
.
Init
(
fd
)
o
.
newsock
=
s
_
,
err
=
iosrv
.
ExecIO
(
&
o
,
0
)
if
err
!=
nil
{
closesocket
(
s
)
return
nil
,
&
OpError
{
"AcceptEx"
,
fd
.
net
,
fd
.
laddr
,
os
.
Errno
(
r
.
errno
)}
return
nil
,
err
}
// Inherit properties of the listening socket.
e
=
syscall
.
SetsockoptInt
(
s
,
syscall
.
SOL_SOCKET
,
syscall
.
SO_UPDATE_ACCEPT_CONTEXT
,
fd
.
sysfd
)
if
e
!=
0
{
closesocket
(
s
)
return
nil
,
&
OpError
{
"Setsockopt"
,
fd
.
net
,
fd
.
laddr
,
os
.
Errno
(
r
.
errno
)}
return
nil
,
err
}
// Get local and peer addr out of AcceptEx buffer.
lsa
,
rsa
:=
syscall
.
GetAcceptIOCPSockaddrs
(
attrs
)
// Create our netFD and return it for further use.
laddr
:=
toAddr
(
lsa
)
raddr
:=
toAddr
(
rsa
)
f
:=
&
netFD
{
sysfd
:
s
,
family
:
fd
.
family
,
proto
:
fd
.
proto
,
cr
:
make
(
chan
*
ioResult
,
1
),
cw
:
make
(
chan
*
ioResult
,
1
),
net
:
fd
.
net
,
laddr
:
laddr
,
raddr
:
raddr
,
}
runtime
.
SetFinalizer
(
f
,
(
*
netFD
)
.
Close
)
return
f
,
nil
}
func
closesocket
(
s
int
)
(
errno
int
)
{
return
syscall
.
Closesocket
(
int32
(
s
))
var
lrsa
,
rrsa
*
syscall
.
RawSockaddrAny
var
llen
,
rlen
int32
l
:=
uint32
(
unsafe
.
Sizeof
(
*
lrsa
))
syscall
.
GetAcceptExSockaddrs
((
*
byte
)(
unsafe
.
Pointer
(
&
o
.
attrs
[
0
])),
0
,
l
,
l
,
&
lrsa
,
&
llen
,
&
rrsa
,
&
rlen
)
lsa
,
_
:=
lrsa
.
Sockaddr
()
rsa
,
_
:=
rrsa
.
Sockaddr
()
return
allocFD
(
s
,
fd
.
family
,
fd
.
proto
,
fd
.
net
,
toAddr
(
lsa
),
toAddr
(
rsa
)),
nil
}
func
init
()
{
var
d
syscall
.
WSAData
e
:=
syscall
.
WSAStartup
(
uint32
(
0x101
),
&
d
)
if
e
!=
0
{
initErr
=
os
.
NewSyscallError
(
"WSAStartup"
,
e
)
}
}
// Not implemeted functions.
func
(
fd
*
netFD
)
dup
()
(
f
*
os
.
File
,
err
os
.
Error
)
{
// TODO: Implement this
...
...
src/pkg/syscall/syscall_windows.go
View file @
0e7995c0
...
...
@@ -653,26 +653,6 @@ func Shutdown(fd, how int) (errno int) {
return
int
(
shutdown
(
int32
(
fd
),
int32
(
how
)))
}
func
AcceptIOCP
(
iocpfd
,
fd
int
,
o
*
Overlapped
)
(
attrs
*
byte
,
errno
int
)
{
// Will ask for local and remote address only.
rsa
:=
make
([]
RawSockaddrAny
,
2
)
attrs
=
(
*
byte
)(
unsafe
.
Pointer
(
&
rsa
[
0
]))
alen
:=
uint32
(
unsafe
.
Sizeof
(
rsa
[
0
]))
var
done
uint32
errno
=
AcceptEx
(
uint32
(
iocpfd
),
uint32
(
fd
),
attrs
,
0
,
alen
,
alen
,
&
done
,
o
)
return
}
func
GetAcceptIOCPSockaddrs
(
attrs
*
byte
)
(
lsa
,
rsa
Sockaddr
)
{
var
lrsa
,
rrsa
*
RawSockaddrAny
var
llen
,
rlen
int32
alen
:=
uint32
(
unsafe
.
Sizeof
(
*
lrsa
))
GetAcceptExSockaddrs
(
attrs
,
0
,
alen
,
alen
,
&
lrsa
,
&
llen
,
&
rrsa
,
&
rlen
)
lsa
,
_
=
lrsa
.
Sockaddr
()
rsa
,
_
=
rrsa
.
Sockaddr
()
return
}
func
WSASendto
(
s
uint32
,
bufs
*
WSABuf
,
bufcnt
uint32
,
sent
*
uint32
,
flags
uint32
,
to
Sockaddr
,
overlapped
*
Overlapped
,
croutine
*
byte
)
(
errno
int
)
{
rsa
,
l
,
err
:=
to
.
sockaddr
()
if
err
!=
0
{
...
...
src/pkg/syscall/ztypes_windows_386.go
View file @
0e7995c0
...
...
@@ -28,6 +28,7 @@ const (
ERROR_PROC_NOT_FOUND
=
127
ERROR_ENVVAR_NOT_FOUND
=
203
ERROR_DIRECTORY
=
267
ERROR_OPERATION_ABORTED
=
995
ERROR_IO_PENDING
=
997
)
...
...
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