Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package net | 5 package net |
brainman
2011/06/03 07:31:57
It doesn't need to be so complicated (I didn't tes
mattn
2011/06/03 11:13:49
Hmm, it can't send large file than 0xffffffff.
| |
6 | 6 |
7 import ( | 7 import ( |
8 "io" | 8 "io" |
9 "os" | 9 "os" |
10 "syscall" | 10 "syscall" |
11 ) | 11 ) |
12 | 12 |
13 type sendfileOp struct { | 13 type sendfileOp struct { |
14 anOp | 14 anOp |
15 » src int32 // source | 15 » src int32 // source |
16 » written int64 | 16 » n uint32 |
17 » remain int64 | |
18 } | 17 } |
19 | 18 |
20 func (o *sendfileOp) Submit() (errno int) { | 19 func (o *sendfileOp) Submit() (errno int) { |
21 » o.written = 0 | 20 » return syscall.TransmitFile(int32(o.fd.sysfd), o.src, o.n, 0, &o.o, nil, syscall.TF_WRITE_BEHIND) |
22 » o.o.HEvent, errno = syscall.CreateEvent(nil, false, false, nil) | |
23 » if errno != 0 { | |
24 » » return | |
25 » } | |
26 » defer syscall.CloseHandle(o.o.HEvent) | |
27 » fd := int32(o.fd.sysfd) | |
28 » for o.remain > 0 { | |
29 » » remain := o.remain | |
30 » » if remain > 0xffffffff { | |
31 » » » remain = 0xffffffff | |
32 » » } | |
33 » » errno = syscall.TransmitFile(fd, o.src, uint32(remain), 0, &o.o, nil, syscall.TF_WRITE_BEHIND) | |
brainman
2011/06/03 07:31:57
Brad, I take it, we start from "current position"
| |
34 » » if errno == 0 { | |
35 » » » return syscall.ERROR_BAD_ARGUMENTS | |
36 » » } | |
37 » » if errno != syscall.ERROR_IO_PENDING { | |
38 » » » return errno | |
39 » » } | |
40 » » rv, errno := syscall.WaitForSingleObject(o.o.HEvent, syscall.INF INITE) | |
brainman
2011/06/07 00:30:26
I've said it before. I'll say it again. You don't
mattn
2011/06/07 01:21:01
Done.
| |
41 » » if errno != 0 { | |
42 » » » // WAIT_FAILED | |
43 » » » return errno | |
44 » » } | |
45 » » if rv == syscall.WAIT_TIMEOUT { | |
46 » » » return syscall.ERROR_TIMEOUT | |
47 » » } | |
48 » » if rv == syscall.WAIT_ABANDONED { | |
49 » » » return syscall.ERROR_DISCARDED | |
50 » » } | |
51 » » // WAIT_OBJECT_0 | |
52 » » n := uint32(0) | |
53 » » errno = syscall.GetOverlappedResult(fd, &o.o, &n, false) | |
54 » » if errno != 0 { | |
55 » » » return errno | |
56 » » } | |
57 » » o.written += int64(n) | |
58 » » o.remain -= int64(n) | |
59 » » if o.remain <= 0 { | |
60 » » » break | |
61 » » } | |
62 » } | |
63 » return | |
64 } | 21 } |
65 | 22 |
66 func (o *sendfileOp) Name() string { | 23 func (o *sendfileOp) Name() string { |
67 return "TransmitFile" | 24 return "TransmitFile" |
68 } | 25 } |
69 | 26 |
70 // sendFile copies the contents of r to c using the TransmitFile | 27 // sendFile copies the contents of r to c using the TransmitFile |
71 // system call to minimize copies. | 28 // system call to minimize copies. |
72 // | 29 // |
73 // if handled == true, sendFile returns the number of bytes copied and any | 30 // if handled == true, sendFile returns the number of bytes copied and any |
74 // non-EOF error. | 31 // non-EOF error. |
75 // | 32 // |
76 // if handled == false, sendFile performed no work. | 33 // if handled == false, sendFile performed no work. |
34 // | |
35 // Note that sendfile for windows does not suppport >2GB file. | |
77 func sendFile(c *netFD, r io.Reader) (written int64, err os.Error, handled bool) { | 36 func sendFile(c *netFD, r io.Reader) (written int64, err os.Error, handled bool) { |
78 » var remain int64 = 1 << 62 // by default, copy until EOF | 37 » var n int64 = 0 // by default, copy until EOF |
79 | 38 |
80 lr, ok := r.(*io.LimitedReader) | 39 lr, ok := r.(*io.LimitedReader) |
81 if ok { | 40 if ok { |
82 » » remain, r = lr.N, lr.R | 41 » » n, r = lr.N, lr.R |
83 » » if remain <= 0 { | 42 » » if n <= 0 { |
84 return 0, nil, true | 43 return 0, nil, true |
85 } | 44 } |
86 } | 45 } |
87 f, ok := r.(*os.File) | 46 f, ok := r.(*os.File) |
88 if !ok { | 47 if !ok { |
89 return 0, nil, false | 48 return 0, nil, false |
90 } | 49 } |
91 | 50 |
92 c.wio.Lock() | 51 c.wio.Lock() |
93 defer c.wio.Unlock() | 52 defer c.wio.Unlock() |
94 c.incref() | 53 c.incref() |
95 defer c.decref() | 54 defer c.decref() |
96 | 55 |
97 var o sendfileOp | 56 var o sendfileOp |
98 o.Init(c) | 57 o.Init(c) |
99 » o.remain = remain | 58 » o.n = uint32(n) |
100 o.src = int32(f.Fd()) | 59 o.src = int32(f.Fd()) |
101 | 60 » done, err := iosrv.ExecIO(&o, 0) |
102 » _, err = iosrv.ExecIO(&o, 0) | 61 » if err != nil { |
62 » » return 0, err, false | |
63 » } | |
103 if lr != nil { | 64 if lr != nil { |
104 » » lr.N = o.remain | 65 » » lr.N -= int64(done) |
105 } | 66 } |
106 » return o.written, err, o.written > 0 | 67 » return int64(done), nil, true |
107 } | 68 } |
LEFT | RIGHT |