socket.scm 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; Sockets
  3. (define-record-type socket :socket
  4. (really-make-socket address-family type
  5. channel condvar
  6. input-port output-port)
  7. socket?
  8. (address-family socket-address-family)
  9. (type socket-socket-type)
  10. (channel socket-channel)
  11. (condvar socket-condvar) ; for blocking until a connection arrives
  12. (input-port socket-input-port set-socket-input-port!)
  13. (output-port socket-output-port set-socket-output-port!))
  14. (define-record-discloser :socket
  15. (lambda (s)
  16. (list 'socket
  17. (socket-address-family s)
  18. (socket-socket-type s)
  19. (socket-channel s))))
  20. (define (channel->socket family type channel)
  21. (really-make-socket family type
  22. channel
  23. (make-condvar) #f #f))
  24. (define (attach-socket-ports! socket output-channel)
  25. (let ((input-channel (socket-channel socket)))
  26. (set-socket-input-port!
  27. socket
  28. (input-channel+closer->port input-channel close-socket-input-channel))
  29. (set-socket-output-port!
  30. socket
  31. (output-channel+closer->port output-channel close-socket-output-channel))))
  32. (define make-socket
  33. (opt-lambda (family type (protocol 0)) ; ####
  34. (channel->socket family type
  35. (external-socket (address-family->raw family)
  36. (socket-type->raw type)
  37. protocol))))
  38. (import-lambda-definition-2 external-socket (family type protocol)
  39. "s48_socket")
  40. (define (dup-socket sock)
  41. (channel->socket (socket-address-family sock)
  42. (socket-socket-type sock)
  43. (external-dup-socket-channel (socket-channel sock))))
  44. (define (port->socket port family type)
  45. (channel->socket family type
  46. (external-dup-socket-channel (port->channel port))))
  47. (define make-socket-pair
  48. (opt-lambda (family type (protocol 0))
  49. (let ((p (external-socketpair (address-family->raw family)
  50. (socket-type->raw type)
  51. protocol)))
  52. (let ((s1 (channel->socket family type (car p)))
  53. (s2 (channel->socket family type (cdr p))))
  54. (attach-socket-ports! s1 (external-dup-socket-channel (car p)))
  55. (attach-socket-ports! s2 (external-dup-socket-channel (cdr p)))
  56. (values s1 s2)))))
  57. (import-lambda-definition-2 external-socketpair (family type protocol)
  58. "s48_socketpair")
  59. ; Close the channel, notifying any waiters that this has happened.
  60. (define (close-socket socket)
  61. (cond
  62. ((or (socket-input-port socket) (socket-output-port socket))
  63. (cond
  64. ((socket-input-port socket) => close-input-port))
  65. (cond
  66. ((socket-output-port socket) => close-output-port)))
  67. (else
  68. (let ((channel (socket-channel socket)))
  69. (with-new-proposal (lose)
  70. (or (channel-maybe-commit-and-close channel close-channel)
  71. (lose)))))))
  72. (define (bind-socket socket address)
  73. (external-bind (socket-channel socket)
  74. (socket-address-raw address)))
  75. (import-lambda-definition-2 external-bind (channel address)
  76. "s48_bind")
  77. (define socket-listen
  78. (opt-lambda (socket (queue-size (max-socket-connection-count)))
  79. (external-listen (socket-channel socket)
  80. queue-size)))
  81. (import-lambda-definition-2 external-listen (channel queue-size)
  82. "s48_listen")
  83. (import-lambda-definition-2 max-socket-connection-count ()
  84. "s48_max_connection_count")
  85. ; FreeBSD's connect() behaves oddly. If you get told to wait, wait for select()
  86. ; to signal the all-clear, and then try to connect again, you get an `already
  87. ; connected' error. To handle this we pass in a RETRY? flag. If RETRY? is
  88. ; true the `already connected' error is ignored.
  89. (define (socket-connect socket address)
  90. (let ((channel (socket-channel socket))
  91. (raw-address (socket-address-raw address)))
  92. (let loop ((retry? #f))
  93. (disable-interrupts!)
  94. (let ((output-channel (external-connect channel raw-address retry?)))
  95. (cond ((channel? output-channel)
  96. (enable-interrupts!)
  97. (attach-socket-ports! socket output-channel))
  98. ((eq? output-channel #t)
  99. (assertion-violation 'socket-client
  100. "client socket already connected"
  101. socket address))
  102. (else
  103. (let ((condvar (make-condvar)))
  104. (wait-for-channel channel condvar)
  105. (with-new-proposal (lose)
  106. (maybe-commit-and-wait-for-condvar condvar))
  107. (enable-interrupts!)
  108. (loop #t))))))))
  109. (import-lambda-definition-2 external-connect (channel address retry?)
  110. "s48_connect")
  111. (define (socket-accept socket)
  112. (let* ((pair (blocking-socket-op socket external-accept))
  113. (channel (car pair))
  114. (newsock (channel->socket (socket-address-family socket)
  115. (socket-socket-type socket)
  116. channel)))
  117. (attach-socket-ports! newsock (external-dup-socket-channel channel))
  118. (values newsock
  119. (raw->socket-address (cdr pair)))))
  120. (import-lambda-definition-2 external-accept (channel retry?)
  121. "s48_accept")
  122. (import-lambda-definition-2 external-dup-socket-channel (channel)
  123. "s48_dup_socket_channel")
  124. ; Keep performing OP until it returns a non-#F value. In between attempts we
  125. ; block on the socket's channel.
  126. (define (blocking-socket-op socket op)
  127. (let ((channel (socket-channel socket))
  128. (condvar (socket-condvar socket)))
  129. (let loop ((retry? #f))
  130. (disable-interrupts!)
  131. (cond ((op channel retry?)
  132. => (lambda (result)
  133. (enable-interrupts!)
  134. result))
  135. (else
  136. (wait-for-channel channel condvar)
  137. (with-new-proposal (lose)
  138. (maybe-commit-and-wait-for-condvar condvar))
  139. (enable-interrupts!)
  140. (loop #t))))))
  141. ;----------------
  142. ; We need to explicitly close socket channels.
  143. (define-enumeration shutdown-option
  144. (read write read/write)
  145. shutdown-option-set)
  146. (define shutdown-option->raw (enum-set-indexer (shutdown-option-set)))
  147. (define (shutdown-socket socket how)
  148. (shutdown-socket-channel (socket-channel socket) how))
  149. (define (shutdown-socket-channel channel how)
  150. (external-shutdown channel (shutdown-option->raw how)))
  151. (import-lambda-definition-2 external-shutdown (channel how)
  152. "s48_shutdown")
  153. (define (close-socket-input-channel channel)
  154. (shutdown-socket-channel channel (shutdown-option read))
  155. (close-channel channel))
  156. (define (close-socket-output-channel channel)
  157. (shutdown-socket-channel channel (shutdown-option write))
  158. (close-channel channel))
  159. (define (socket-address socket)
  160. (raw->socket-address
  161. (external-getsockname (socket-channel socket))))
  162. (import-lambda-definition-2 external-getsockname (channel)
  163. "s48_getsockname")
  164. (define (socket-peer-address socket)
  165. (raw->socket-address
  166. (external-getpeername (socket-channel socket))))
  167. (import-lambda-definition-2 external-getpeername (channel)
  168. "s48_getpeername")
  169. (define-syntax define-socket-option-setter
  170. (syntax-rules ()
  171. ((define-socket-option-setter ?name ?external-name)
  172. (begin
  173. (define (?name socket val)
  174. (external-setsockopt (socket-channel socket) val))
  175. (import-lambda-definition-2 external-setsockopt (channel val)
  176. ?external-name)))))
  177. (define-syntax define-socket-option-getter
  178. (syntax-rules ()
  179. ((define-socket-option-getter ?name ?external-name)
  180. (begin
  181. (define (?name socket)
  182. (external-getsockopt (socket-channel socket)))
  183. (import-lambda-definition-2 external-getsockopt (channel)
  184. ?external-name)))))
  185. (define-socket-option-setter set-socket-debug?!
  186. "s48_setsockopt_SO_DEBUG")
  187. (define-socket-option-getter socket-debug?!
  188. "s48_getsockopt_SO_DEBUG")
  189. (define-socket-option-setter set-socket-accept-connections?!
  190. "s48_setsockopt_SO_ACCEPTCONN")
  191. (define-socket-option-getter socket-accept-connections?
  192. "s48_getsockopt_SO_ACCEPTCONN")
  193. (define-socket-option-setter set-socket-broadcast?!
  194. "s48_setsockopt_SO_BROADCAST")
  195. (define-socket-option-getter socket-broadcast?
  196. "s48_getsockopt_SO_BROADCAST")
  197. (define-socket-option-setter set-socket-reuse-address?!
  198. "s48_setsockopt_SO_REUSEADDR")
  199. (define-socket-option-getter socket-reuse-address?
  200. "s48_getsockopt_SO_REUSEADDR")
  201. (define-socket-option-setter set-socket-keepalive?!
  202. "s48_setsockopt_SO_KEEPALIVE")
  203. (define-socket-option-getter socket-keepalive?
  204. "s48_getsockopt_SO_KEEPALIVE")
  205. (define-socket-option-setter set-socket-oob-inline?!
  206. "s48_setsockopt_SO_OOBINLINE")
  207. (define-socket-option-getter socket-oob-inline?
  208. "s48_getsockopt_SO_OOBINLINE")
  209. (define-socket-option-setter set-socket-send-buffer-size!
  210. "s48_setsockopt_SO_SNDBUF")
  211. (define-socket-option-getter socket-send-buffer-size
  212. "s48_getsockopt_SO_SNDBUF")
  213. (define-socket-option-setter set-socket-receive-buffer-size!
  214. "s48_setsockopt_SO_RCVBUF")
  215. (define-socket-option-getter socket-receive-buffer-size
  216. "s48_getsockopt_SO_RCVBUF")
  217. (define-socket-option-getter socket-error
  218. "s48_getsockopt_SO_ERROR")
  219. (define-socket-option-setter set-socket-dontroute?!
  220. "s48_setsockopt_SO_DONTROUTE")
  221. (define-socket-option-getter socket-dontroute?
  222. "s48_getsockopt_SO_DONTROUTE")
  223. (define-socket-option-setter set-socket-minimum-receive-count!
  224. "s48_setsockopt_SO_RCVLOWAT")
  225. (define-socket-option-getter socket-minimum-receive-count
  226. "s48_getsockopt_SO_RCVLOWAT")
  227. (define-socket-option-setter set-socket-minimum-send-count!
  228. "s48_setsockopt_SO_SNDLOWAT")
  229. (define-socket-option-getter socket-minimum-send-count
  230. "s48_getsockopt_SO_SNDLOWAT")
  231. (define-socket-option-setter set-socket-tcp-nodelay?!
  232. "s48_setsockopt_TCP_NODELAY")
  233. (define-socket-option-getter socket-tcp-nodelay?
  234. "s48_getsockopt_TCP_NODELAY")
  235. (define-socket-option-setter set-socket-ipv6-unicast-hops!
  236. "s48_setsockopt_IPV6_UNICAST_HOPS")
  237. (define-socket-option-getter socket-ipv6-unicast-hops
  238. "s48_getsockopt_IPV6_UNICAST_HOPS")
  239. (define-socket-option-setter set-socket-ipv6-multicast-interface!
  240. "s48_setsockopt_IPV6_MULTICAST_IF")
  241. (define-socket-option-getter socket-ipv6-multicast-interface
  242. "s48_getsockopt_IPV6_MULTICAST_IF")
  243. (define-socket-option-setter set-socket-ipv6-multicast-hops!
  244. "s48_setsockopt_IPV6_MULTICAST_HOPS")
  245. (define-socket-option-getter socket-ipv6-multicast-hops
  246. "s48_getsockopt_IPV6_MULTICAST_HOPS")
  247. (define-socket-option-setter set-socket-ipv6-multicast-loop?!
  248. "s48_setsockopt_IPV6_MULTICAST_LOOP")
  249. (define-socket-option-getter socket-ipv6-multicast-loop?
  250. "s48_getsockopt_IPV6_MULTICAST_LOOP")
  251. (define (socket-ipv6-join-group! socket address interface)
  252. (external-ipv6-socket-join-group (socket-channel socket)
  253. (socket-address-raw address)
  254. (interface-index interface)))
  255. (import-lambda-definition-2 external-ipv6-socket-join-group (channel address if-index)
  256. "s48_ipv6_socket_join_group")
  257. (define (socket-ipv6-leave-group! socket address interface)
  258. (external-ipv6-socket-leave-group (socket-channel socket)
  259. (socket-address-raw address)
  260. (interface-index interface)))
  261. (import-lambda-definition-2 external-ipv6-socket-leave-group (channel address if-index)
  262. "s48_ipv6_socket_leave_group")
  263. ; Messages
  264. (define-enumeration message-option
  265. (oob peek dontroute)
  266. message-options)
  267. (define socket-send
  268. (opt-lambda (socket
  269. buffer
  270. (start 0)
  271. (count (byte-vector-length buffer))
  272. (address (socket-peer-address socket)) ; cache this?
  273. (flags (message-options)))
  274. (blocking-socket-op socket
  275. (lambda (channel retry?)
  276. (external-sendto channel buffer start count
  277. (enum-set->integer flags)
  278. (socket-address-raw address)
  279. retry?)))))
  280. (import-lambda-definition-2 external-sendto (channel
  281. buffer start count flags address
  282. retry?)
  283. "s48_sendto")
  284. (define socket-receive
  285. (opt-lambda (socket
  286. buffer
  287. (start 0)
  288. (count (byte-vector-length buffer))
  289. (want-sender? #t)
  290. (flags (message-options)))
  291. (let ((got
  292. (blocking-socket-op socket
  293. (lambda (channel retry?)
  294. (external-recvfrom channel buffer start count
  295. (enum-set->integer flags)
  296. want-sender?
  297. retry?)))))
  298. (if want-sender?
  299. (values (car got) (raw->socket-address (cdr got)))
  300. got))))
  301. (import-lambda-definition-2 external-recvfrom (channel
  302. buffer start count flags
  303. want-sender? retry?)
  304. "s48_recvfrom")