PageRenderTime 52ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/src/pkg/net/tcpsock.go

http://github.com/ivanwyc/google-go
Go | 280 lines | 179 code | 34 blank | 67 comment | 46 complexity | 9750a59a9aa1713d1f6308f642aaa426 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // TCP sockets
  5. package net
  6. import (
  7. "os"
  8. "syscall"
  9. )
  10. func sockaddrToTCP(sa syscall.Sockaddr) Addr {
  11. switch sa := sa.(type) {
  12. case *syscall.SockaddrInet4:
  13. return &TCPAddr{&sa.Addr, sa.Port}
  14. case *syscall.SockaddrInet6:
  15. return &TCPAddr{&sa.Addr, sa.Port}
  16. }
  17. return nil
  18. }
  19. // TCPAddr represents the address of a TCP end point.
  20. type TCPAddr struct {
  21. IP IP
  22. Port int
  23. }
  24. // Network returns the address's network name, "tcp".
  25. func (a *TCPAddr) Network() string { return "tcp" }
  26. func (a *TCPAddr) String() string { return joinHostPort(a.IP.String(), itoa(a.Port)) }
  27. func (a *TCPAddr) family() int {
  28. if a == nil || len(a.IP) <= 4 {
  29. return syscall.AF_INET
  30. }
  31. if ip := a.IP.To4(); ip != nil {
  32. return syscall.AF_INET
  33. }
  34. return syscall.AF_INET6
  35. }
  36. func (a *TCPAddr) sockaddr(family int) (syscall.Sockaddr, os.Error) {
  37. return ipToSockaddr(family, a.IP, a.Port)
  38. }
  39. func (a *TCPAddr) toAddr() sockaddr {
  40. if a == nil { // nil *TCPAddr
  41. return nil // nil interface
  42. }
  43. return a
  44. }
  45. // ResolveTCPAddr parses addr as a TCP address of the form
  46. // host:port and resolves domain names or port names to
  47. // numeric addresses. A literal IPv6 host address must be
  48. // enclosed in square brackets, as in "[::]:80".
  49. func ResolveTCPAddr(addr string) (*TCPAddr, os.Error) {
  50. ip, port, err := hostPortToIP("tcp", addr)
  51. if err != nil {
  52. return nil, err
  53. }
  54. return &TCPAddr{ip, port}, nil
  55. }
  56. // TCPConn is an implementation of the Conn interface
  57. // for TCP network connections.
  58. type TCPConn struct {
  59. fd *netFD
  60. }
  61. func newTCPConn(fd *netFD) *TCPConn {
  62. c := &TCPConn{fd}
  63. setsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, 1)
  64. return c
  65. }
  66. func (c *TCPConn) ok() bool { return c != nil && c.fd != nil }
  67. // Implementation of the Conn interface - see Conn for documentation.
  68. // Read reads data from the TCP connection.
  69. //
  70. // Read can be made to time out and return err == os.EAGAIN
  71. // after a fixed time limit; see SetTimeout and SetReadTimeout.
  72. func (c *TCPConn) Read(b []byte) (n int, err os.Error) {
  73. if !c.ok() {
  74. return 0, os.EINVAL
  75. }
  76. return c.fd.Read(b)
  77. }
  78. // Write writes data to the TCP connection.
  79. //
  80. // Write can be made to time out and return err == os.EAGAIN
  81. // after a fixed time limit; see SetTimeout and SetReadTimeout.
  82. func (c *TCPConn) Write(b []byte) (n int, err os.Error) {
  83. if !c.ok() {
  84. return 0, os.EINVAL
  85. }
  86. return c.fd.Write(b)
  87. }
  88. // Close closes the TCP connection.
  89. func (c *TCPConn) Close() os.Error {
  90. if !c.ok() {
  91. return os.EINVAL
  92. }
  93. err := c.fd.Close()
  94. c.fd = nil
  95. return err
  96. }
  97. // LocalAddr returns the local network address, a *TCPAddr.
  98. func (c *TCPConn) LocalAddr() Addr {
  99. if !c.ok() {
  100. return nil
  101. }
  102. return c.fd.laddr
  103. }
  104. // RemoteAddr returns the remote network address, a *TCPAddr.
  105. func (c *TCPConn) RemoteAddr() Addr {
  106. if !c.ok() {
  107. return nil
  108. }
  109. return c.fd.raddr
  110. }
  111. // SetTimeout sets the read and write deadlines associated
  112. // with the connection.
  113. func (c *TCPConn) SetTimeout(nsec int64) os.Error {
  114. if !c.ok() {
  115. return os.EINVAL
  116. }
  117. return setTimeout(c.fd, nsec)
  118. }
  119. // SetReadTimeout sets the time (in nanoseconds) that
  120. // Read will wait for data before returning os.EAGAIN.
  121. // Setting nsec == 0 (the default) disables the deadline.
  122. func (c *TCPConn) SetReadTimeout(nsec int64) os.Error {
  123. if !c.ok() {
  124. return os.EINVAL
  125. }
  126. return setReadTimeout(c.fd, nsec)
  127. }
  128. // SetWriteTimeout sets the time (in nanoseconds) that
  129. // Write will wait to send its data before returning os.EAGAIN.
  130. // Setting nsec == 0 (the default) disables the deadline.
  131. // Even if write times out, it may return n > 0, indicating that
  132. // some of the data was successfully written.
  133. func (c *TCPConn) SetWriteTimeout(nsec int64) os.Error {
  134. if !c.ok() {
  135. return os.EINVAL
  136. }
  137. return setWriteTimeout(c.fd, nsec)
  138. }
  139. // SetReadBuffer sets the size of the operating system's
  140. // receive buffer associated with the connection.
  141. func (c *TCPConn) SetReadBuffer(bytes int) os.Error {
  142. if !c.ok() {
  143. return os.EINVAL
  144. }
  145. return setReadBuffer(c.fd, bytes)
  146. }
  147. // SetWriteBuffer sets the size of the operating system's
  148. // transmit buffer associated with the connection.
  149. func (c *TCPConn) SetWriteBuffer(bytes int) os.Error {
  150. if !c.ok() {
  151. return os.EINVAL
  152. }
  153. return setWriteBuffer(c.fd, bytes)
  154. }
  155. // SetLinger sets the behavior of Close() on a connection
  156. // which still has data waiting to be sent or to be acknowledged.
  157. //
  158. // If sec < 0 (the default), Close returns immediately and
  159. // the operating system finishes sending the data in the background.
  160. //
  161. // If sec == 0, Close returns immediately and the operating system
  162. // discards any unsent or unacknowledged data.
  163. //
  164. // If sec > 0, Close blocks for at most sec seconds waiting for
  165. // data to be sent and acknowledged.
  166. func (c *TCPConn) SetLinger(sec int) os.Error {
  167. if !c.ok() {
  168. return os.EINVAL
  169. }
  170. return setLinger(c.fd, sec)
  171. }
  172. // SetKeepAlive sets whether the operating system should send
  173. // keepalive messages on the connection.
  174. func (c *TCPConn) SetKeepAlive(keepalive bool) os.Error {
  175. if !c.ok() {
  176. return os.EINVAL
  177. }
  178. return setKeepAlive(c.fd, keepalive)
  179. }
  180. // DialTCP is like Dial but can only connect to TCP networks
  181. // and returns a TCPConn structure.
  182. func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err os.Error) {
  183. if raddr == nil {
  184. return nil, &OpError{"dial", "tcp", nil, errMissingAddress}
  185. }
  186. fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_STREAM, "dial", sockaddrToTCP)
  187. if e != nil {
  188. return nil, e
  189. }
  190. return newTCPConn(fd), nil
  191. }
  192. // TCPListener is a TCP network listener.
  193. // Clients should typically use variables of type Listener
  194. // instead of assuming TCP.
  195. type TCPListener struct {
  196. fd *netFD
  197. }
  198. // ListenTCP announces on the TCP address laddr and returns a TCP listener.
  199. // Net must be "tcp", "tcp4", or "tcp6".
  200. // If laddr has a port of 0, it means to listen on some available port.
  201. // The caller can use l.Addr() to retrieve the chosen address.
  202. func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err os.Error) {
  203. fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_STREAM, "listen", sockaddrToTCP)
  204. if err != nil {
  205. return nil, err
  206. }
  207. errno := syscall.Listen(fd.sysfd, listenBacklog())
  208. if errno != 0 {
  209. syscall.Close(fd.sysfd)
  210. return nil, &OpError{"listen", "tcp", laddr, os.Errno(errno)}
  211. }
  212. l = new(TCPListener)
  213. l.fd = fd
  214. return l, nil
  215. }
  216. // AcceptTCP accepts the next incoming call and returns the new connection
  217. // and the remote address.
  218. func (l *TCPListener) AcceptTCP() (c *TCPConn, err os.Error) {
  219. if l == nil || l.fd == nil || l.fd.sysfd < 0 {
  220. return nil, os.EINVAL
  221. }
  222. fd, err := l.fd.accept(sockaddrToTCP)
  223. if err != nil {
  224. return nil, err
  225. }
  226. return newTCPConn(fd), nil
  227. }
  228. // Accept implements the Accept method in the Listener interface;
  229. // it waits for the next call and returns a generic Conn.
  230. func (l *TCPListener) Accept() (c Conn, err os.Error) {
  231. c1, err := l.AcceptTCP()
  232. if err != nil {
  233. return nil, err
  234. }
  235. return c1, nil
  236. }
  237. // Close stops listening on the TCP address.
  238. // Already Accepted connections are not closed.
  239. func (l *TCPListener) Close() os.Error {
  240. if l == nil || l.fd == nil {
  241. return os.EINVAL
  242. }
  243. return l.fd.Close()
  244. }
  245. // Addr returns the listener's network address, a *TCPAddr.
  246. func (l *TCPListener) Addr() Addr { return l.fd.laddr }