PageRenderTime 23ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/go/src/pkg/net/ipsock_plan9.go

http://github.com/vablaya/gopp-cs345
Go | 305 lines | 258 code | 30 blank | 17 comment | 75 complexity | f6d26a9f2313133ec8efc48cf3a9dc3e 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. // IP sockets stubs for Plan 9
  5. package net
  6. import (
  7. "os"
  8. )
  9. // probeIPv6Stack returns two boolean values. If the first boolean value is
  10. // true, kernel supports basic IPv6 functionality. If the second
  11. // boolean value is true, kernel supports IPv6 IPv4-mapping.
  12. func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
  13. return false, false
  14. }
  15. // parsePlan9Addr parses address of the form [ip!]port (e.g. 127.0.0.1!80).
  16. func parsePlan9Addr(s string) (ip IP, iport int, err os.Error) {
  17. var (
  18. addr IP
  19. p, i int
  20. ok bool
  21. )
  22. addr = IPv4zero // address contains port only
  23. i = byteIndex(s, '!')
  24. if i >= 0 {
  25. addr = ParseIP(s[:i])
  26. if addr == nil {
  27. err = os.NewError("net: parsing IP failed")
  28. goto Error
  29. }
  30. }
  31. p, _, ok = dtoi(s[i+1:], 0)
  32. if !ok {
  33. err = os.NewError("net: parsing port failed")
  34. goto Error
  35. }
  36. if p < 0 || p > 0xFFFF {
  37. err = &AddrError{"invalid port", string(p)}
  38. goto Error
  39. }
  40. return addr, p, nil
  41. Error:
  42. return nil, 0, err
  43. }
  44. func readPlan9Addr(proto, filename string) (addr Addr, err os.Error) {
  45. var buf [128]byte
  46. f, err := os.Open(filename)
  47. if err != nil {
  48. return
  49. }
  50. n, err := f.Read(buf[:])
  51. if err != nil {
  52. return
  53. }
  54. ip, port, err := parsePlan9Addr(string(buf[:n]))
  55. if err != nil {
  56. return
  57. }
  58. switch proto {
  59. case "tcp":
  60. addr = &TCPAddr{ip, port}
  61. case "udp":
  62. addr = &UDPAddr{ip, port}
  63. default:
  64. return nil, os.NewError("unknown protocol " + proto)
  65. }
  66. return addr, nil
  67. }
  68. type plan9Conn struct {
  69. proto, name, dir string
  70. ctl, data *os.File
  71. laddr, raddr Addr
  72. }
  73. func newPlan9Conn(proto, name string, ctl *os.File, laddr, raddr Addr) *plan9Conn {
  74. return &plan9Conn{proto, name, "/net/" + proto + "/" + name, ctl, nil, laddr, raddr}
  75. }
  76. func (c *plan9Conn) ok() bool { return c != nil && c.ctl != nil }
  77. // Implementation of the Conn interface - see Conn for documentation.
  78. // Read implements the net.Conn Read method.
  79. func (c *plan9Conn) Read(b []byte) (n int, err os.Error) {
  80. if !c.ok() {
  81. return 0, os.EINVAL
  82. }
  83. if c.data == nil {
  84. c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0)
  85. if err != nil {
  86. return 0, err
  87. }
  88. }
  89. n, err = c.data.Read(b)
  90. if c.proto == "udp" && err == os.EOF {
  91. n = 0
  92. err = nil
  93. }
  94. return
  95. }
  96. // Write implements the net.Conn Write method.
  97. func (c *plan9Conn) Write(b []byte) (n int, err os.Error) {
  98. if !c.ok() {
  99. return 0, os.EINVAL
  100. }
  101. if c.data == nil {
  102. c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0)
  103. if err != nil {
  104. return 0, err
  105. }
  106. }
  107. return c.data.Write(b)
  108. }
  109. // Close closes the connection.
  110. func (c *plan9Conn) Close() os.Error {
  111. if !c.ok() {
  112. return os.EINVAL
  113. }
  114. err := c.ctl.Close()
  115. if err != nil {
  116. return err
  117. }
  118. if c.data != nil {
  119. err = c.data.Close()
  120. }
  121. c.ctl = nil
  122. c.data = nil
  123. return err
  124. }
  125. // LocalAddr returns the local network address.
  126. func (c *plan9Conn) LocalAddr() Addr {
  127. if !c.ok() {
  128. return nil
  129. }
  130. return c.laddr
  131. }
  132. // RemoteAddr returns the remote network address.
  133. func (c *plan9Conn) RemoteAddr() Addr {
  134. if !c.ok() {
  135. return nil
  136. }
  137. return c.raddr
  138. }
  139. // SetTimeout implements the net.Conn SetTimeout method.
  140. func (c *plan9Conn) SetTimeout(nsec int64) os.Error {
  141. if !c.ok() {
  142. return os.EINVAL
  143. }
  144. return os.EPLAN9
  145. }
  146. // SetReadTimeout implements the net.Conn SetReadTimeout method.
  147. func (c *plan9Conn) SetReadTimeout(nsec int64) os.Error {
  148. if !c.ok() {
  149. return os.EINVAL
  150. }
  151. return os.EPLAN9
  152. }
  153. // SetWriteTimeout implements the net.Conn SetWriteTimeout method.
  154. func (c *plan9Conn) SetWriteTimeout(nsec int64) os.Error {
  155. if !c.ok() {
  156. return os.EINVAL
  157. }
  158. return os.EPLAN9
  159. }
  160. func startPlan9(net string, addr Addr) (ctl *os.File, dest, proto, name string, err os.Error) {
  161. var (
  162. ip IP
  163. port int
  164. )
  165. switch a := addr.(type) {
  166. case *TCPAddr:
  167. proto = "tcp"
  168. ip = a.IP
  169. port = a.Port
  170. case *UDPAddr:
  171. proto = "udp"
  172. ip = a.IP
  173. port = a.Port
  174. default:
  175. err = UnknownNetworkError(net)
  176. return
  177. }
  178. clone, dest, err := queryCS1(proto, ip, port)
  179. if err != nil {
  180. return
  181. }
  182. f, err := os.OpenFile(clone, os.O_RDWR, 0)
  183. if err != nil {
  184. return
  185. }
  186. var buf [16]byte
  187. n, err := f.Read(buf[:])
  188. if err != nil {
  189. return
  190. }
  191. return f, dest, proto, string(buf[:n]), nil
  192. }
  193. func dialPlan9(net string, laddr, raddr Addr) (c *plan9Conn, err os.Error) {
  194. f, dest, proto, name, err := startPlan9(net, raddr)
  195. if err != nil {
  196. return
  197. }
  198. _, err = f.WriteString("connect " + dest)
  199. if err != nil {
  200. return
  201. }
  202. laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local")
  203. if err != nil {
  204. return
  205. }
  206. raddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/remote")
  207. if err != nil {
  208. return
  209. }
  210. return newPlan9Conn(proto, name, f, laddr, raddr), nil
  211. }
  212. type plan9Listener struct {
  213. proto, name, dir string
  214. ctl *os.File
  215. laddr Addr
  216. }
  217. func listenPlan9(net string, laddr Addr) (l *plan9Listener, err os.Error) {
  218. f, dest, proto, name, err := startPlan9(net, laddr)
  219. if err != nil {
  220. return
  221. }
  222. _, err = f.WriteString("announce " + dest)
  223. if err != nil {
  224. return
  225. }
  226. laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local")
  227. if err != nil {
  228. return
  229. }
  230. l = new(plan9Listener)
  231. l.proto = proto
  232. l.name = name
  233. l.dir = "/net/" + proto + "/" + name
  234. l.ctl = f
  235. l.laddr = laddr
  236. return l, nil
  237. }
  238. func (l *plan9Listener) plan9Conn() *plan9Conn {
  239. return newPlan9Conn(l.proto, l.name, l.ctl, l.laddr, nil)
  240. }
  241. func (l *plan9Listener) acceptPlan9() (c *plan9Conn, err os.Error) {
  242. f, err := os.Open(l.dir + "/listen")
  243. if err != nil {
  244. return
  245. }
  246. var buf [16]byte
  247. n, err := f.Read(buf[:])
  248. if err != nil {
  249. return
  250. }
  251. name := string(buf[:n])
  252. laddr, err := readPlan9Addr(l.proto, l.dir+"/local")
  253. if err != nil {
  254. return
  255. }
  256. raddr, err := readPlan9Addr(l.proto, l.dir+"/remote")
  257. if err != nil {
  258. return
  259. }
  260. return newPlan9Conn(l.proto, name, f, laddr, raddr), nil
  261. }
  262. func (l *plan9Listener) Accept() (c Conn, err os.Error) {
  263. c1, err := l.acceptPlan9()
  264. if err != nil {
  265. return
  266. }
  267. return c1, nil
  268. }
  269. func (l *plan9Listener) Close() os.Error {
  270. if l == nil || l.ctl == nil {
  271. return os.EINVAL
  272. }
  273. return l.ctl.Close()
  274. }
  275. func (l *plan9Listener) Addr() Addr { return l.laddr }