PageRenderTime 57ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/contrib/sockets/sockets.lisp

https://gitlab.com/jlarocco/ecl
Lisp | 1668 lines | 1352 code | 207 blank | 109 comment | 96 complexity | af3db119710dc06685c90ee9119557da MD5 | raw file
Possible License(s): LGPL-2.0, JSON

Large files files are truncated, but you can click here to view the full file

  1. ;; -*- Mode: Lisp; Syntax: Common-Lisp -*-
  2. ;; $Id$
  3. ;; This file is based on SBCL's SB-BSD-SOCKET module and has been
  4. ;; heavily modified to work with ECL by Julian Stecklina.
  5. ;; Port to Windows Sockets contributed by M. Goffioul.
  6. ;; You may do whatever you want with this file. (PUBLIC DOMAIN)
  7. ;; Trivial stuff is copied from SBCL's SB-BSD-SOCKETS, which is also
  8. ;; in the public domain.
  9. (in-package "SB-BSD-SOCKETS")
  10. ;; Obviously this requires the one or other form of BSD compatible
  11. ;; socket interface.
  12. #+(or :win32 :mingw32)
  13. (eval-when (:compile-toplevel :load-toplevel :execute)
  14. (push :wsock *features*))
  15. ;; Include the neccessary headers
  16. #-:wsock
  17. (clines
  18. "#include <sys/types.h>"
  19. "#include <sys/socket.h>"
  20. "#include <sys/un.h>"
  21. "#define wincoerce(t,x) (x)"
  22. #-:win32
  23. "#include <sys/time.h>"
  24. "#include <netdb.h>"
  25. "#include <string.h>"
  26. "#include <unistd.h>"
  27. "#include <netinet/in.h>"
  28. "#include <netinet/tcp.h>"
  29. "#include <errno.h>"
  30. "#include <fcntl.h>"
  31. #+:cygwin
  32. "#ifndef MSG_WAITALL
  33. #define MSG_WAITALL 0
  34. #endif"
  35. "#ifndef MSG_CONFIRM"
  36. "#define MSG_CONFIRM 0"
  37. "#endif"
  38. "#ifndef MSG_NOSIGNAL"
  39. "#define MSG_NOSIGNAL 0"
  40. "#endif"
  41. "#ifndef MSG_DONTWAIT"
  42. "#define MSG_DONTWAIT 0"
  43. "#endif"
  44. "#ifndef MSG_EOR"
  45. "#define MSG_EOR 0"
  46. "#endif")
  47. #+:wsock
  48. (clines
  49. "#include <winsock2.h>"
  50. "typedef unsigned int uint32_t;"
  51. "#define wincoerce(t,x) ((t)(x))"
  52. #-:mingw32
  53. "typedef int ssize_t;"
  54. "typedef int socklen_t;"
  55. "#define MSG_WAITALL 0"
  56. "#define MSG_EOR 0"
  57. "#define MSG_DONTWAIT 0"
  58. "#define MSG_NOSIGNAL 0"
  59. "#define MSG_CONFIRM 0"
  60. "#include <errno.h>"
  61. "#include <fcntl.h>"
  62. "#include <stdio.h>")
  63. #+:wsock
  64. (progn
  65. (defvar +wsock-initialized+ nil)
  66. (defun wsock-initialize ()
  67. (unless +wsock-initialized+
  68. (if (c-inline () () :object
  69. "
  70. {
  71. WSADATA wsadata;
  72. cl_object output;
  73. ecl_disable_interrupts();
  74. if (WSAStartup(MAKEWORD(2,2), &wsadata) == NO_ERROR)
  75. output = ECL_T;
  76. else
  77. output = ECL_NIL;
  78. ecl_enable_interrupts();
  79. @(return) = output;
  80. }")
  81. (setf +wsock-initialized+ t)
  82. (error "Unable to initialize Windows Socket library"))))
  83. (wsock-initialize)
  84. ); #+:wsock
  85. (eval-when (:compile-toplevel :execute)
  86. (defmacro c-constant (c-name)
  87. `(c-inline () () :int ,c-name :one-liner t))
  88. (defmacro define-c-constants (&rest args)
  89. `(let () ; Prevents evaluation of constant value form
  90. ,@(loop
  91. for (lisp-name c-name) on args by #'cddr
  92. collect `(defconstant ,lisp-name (c-constant ,c-name))))))
  93. #+:wsock
  94. (Clines
  95. "#define AF_LOCAL -1"
  96. )
  97. (define-c-constants
  98. +af-inet+ "AF_INET"
  99. +af-local+ #-sun4sol2 "AF_LOCAL" #+sun4sol2 "AF_UNIX"
  100. +eagain+ "EAGAIN"
  101. +eintr+ "EINTR")
  102. #+:wsock
  103. (defconstant +af-named-pipe+ -2)
  104. ;; Foreign functions
  105. (defentry ff-socket (:int :int :int) (:int "socket") :no-interrupts t)
  106. (defentry ff-listen (:int :int) (:int "listen") :no-interrupts t)
  107. (defentry ff-close (:int) (:int "close") :no-interrupts t)
  108. #+:wsock (defentry ff-closesocket (:int) (:int "closesocket") :no-interrupts t)
  109. ;;; This courtesy of Pierre Mai in comp.lang.lisp 08 Jan 1999 00:51:44 +0100
  110. ;;; Message-ID: <87lnjebq0f.fsf@orion.dent.isdn.cs.tu-berlin.de>
  111. (defun split (string &optional max (ws '(#\Space #\Tab)))
  112. "Split `string' along whitespace as defined by the sequence `ws'.
  113. The whitespace is elided from the result. The whole string will be
  114. split, unless `max' is a non-negative integer, in which case the
  115. string will be split into `max' tokens at most, the last one
  116. containing the whole rest of the given `string', if any."
  117. (flet ((is-ws (char) (find char ws)))
  118. (loop for start = (position-if-not #'is-ws string)
  119. then (position-if-not #'is-ws string :start index)
  120. for index = (and start
  121. (if (and max (= (1+ word-count) max))
  122. nil
  123. (position-if #'is-ws string :start start)))
  124. while start
  125. collect (subseq string start index)
  126. count 1 into word-count
  127. while index)))
  128. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  129. ;;;
  130. ;;; NAME RESOLVING
  131. ;;;
  132. (defclass host-ent ()
  133. ((name :initarg :name :accessor host-ent-name)
  134. (aliases :initarg :aliases :accessor host-ent-aliases)
  135. (address-type :initarg :type :accessor host-ent-address-type)
  136. ; presently always AF_INET
  137. (addresses :initarg :addresses :accessor host-ent-addresses))
  138. (:documentation ""))
  139. (defgeneric host-ent-address (host-ent)
  140. (:documentation ""))
  141. (defmethod host-ent-address ((host-ent host-ent))
  142. (car (host-ent-addresses host-ent)))
  143. ;; FIXME: We should move this to using getaddrinfo
  144. (defun get-host-by-name (host-name)
  145. "Returns a HOST-ENT instance for HOST-NAME or throws some kind of condition.
  146. HOST-NAME may also be an IP address in dotted quad notation or some other
  147. weird stuff - see gethostbyname(3) for grisly details."
  148. (let ((host-ent (make-instance 'host-ent)))
  149. (if (c-inline (host-name host-ent
  150. #'(setf host-ent-name)
  151. #'(setf host-ent-aliases)
  152. #'(setf host-ent-address-type)
  153. #'(setf host-ent-addresses))
  154. (:cstring t t t t t) t
  155. "
  156. {
  157. struct hostent *hostent = gethostbyname(#0);
  158. if (hostent != NULL) {
  159. char **aliases;
  160. char **addrs;
  161. cl_object aliases_list = ECL_NIL;
  162. cl_object addr_list = ECL_NIL;
  163. int length = hostent->h_length;
  164. funcall(3,#2,make_simple_base_string(hostent->h_name),#1);
  165. funcall(3,#4,ecl_make_integer(hostent->h_addrtype),#1);
  166. for (aliases = hostent->h_aliases; *aliases != NULL; aliases++) {
  167. aliases_list = CONS(make_simple_base_string(*aliases),aliases_list);
  168. }
  169. funcall(3,#3,aliases_list,#1);
  170. for (addrs = hostent->h_addr_list; *addrs != NULL; addrs++) {
  171. int pos;
  172. cl_object vector = funcall(2,@make-array,MAKE_FIXNUM(length));
  173. for (pos = 0; pos < length; pos++)
  174. ecl_aset(vector, pos, MAKE_FIXNUM((unsigned char)((*addrs)[pos])));
  175. addr_list = CONS(vector, addr_list);
  176. }
  177. funcall(3,#5,addr_list,#1);
  178. @(return) = #1;
  179. } else {
  180. @(return) = ECL_NIL;
  181. }
  182. }"
  183. :side-effects t)
  184. host-ent
  185. (name-service-error "get-host-by-name"))))
  186. (defun get-host-by-address (address)
  187. (assert (and (typep address 'vector)
  188. (= (length address) 4)))
  189. (let ((host-ent (make-instance 'host-ent)))
  190. (if
  191. (c-inline (address host-ent
  192. #'(setf host-ent-name)
  193. #'(setf host-ent-aliases)
  194. #'(setf host-ent-address-type)
  195. #'(setf host-ent-addresses))
  196. (t t t t t t) t
  197. "
  198. {
  199. unsigned char vector[4];
  200. struct hostent *hostent;
  201. vector[0] = fixint(ecl_aref(#0,0));
  202. vector[1] = fixint(ecl_aref(#0,1));
  203. vector[2] = fixint(ecl_aref(#0,2));
  204. vector[3] = fixint(ecl_aref(#0,3));
  205. ecl_disable_interrupts();
  206. hostent = gethostbyaddr(wincoerce(const char *, vector),4,AF_INET);
  207. ecl_enable_interrupts();
  208. if (hostent != NULL) {
  209. char **aliases;
  210. char **addrs;
  211. cl_object aliases_list = ECL_NIL;
  212. cl_object addr_list = ECL_NIL;
  213. int length = hostent->h_length;
  214. funcall(3,#2,make_simple_base_string(hostent->h_name),#1);
  215. funcall(3,#4,ecl_make_integer(hostent->h_addrtype),#1);
  216. for (aliases = hostent->h_aliases; *aliases != NULL; aliases++) {
  217. aliases_list = CONS(make_simple_base_string(*aliases),aliases_list);
  218. }
  219. funcall(3,#3,aliases_list,#1);
  220. for (addrs = hostent->h_addr_list; *addrs != NULL; addrs++) {
  221. int pos;
  222. cl_object vector = funcall(2,@make-array,MAKE_FIXNUM(length));
  223. for (pos = 0; pos < length; pos++)
  224. ecl_aset(vector, pos, MAKE_FIXNUM((unsigned char)((*addrs)[pos])));
  225. addr_list = CONS(vector, addr_list);
  226. }
  227. funcall(3,#5,addr_list,#1);
  228. @(return) = #1;
  229. } else {
  230. @(return) = ECL_NIL;
  231. }
  232. }"
  233. :side-effects t)
  234. host-ent
  235. (name-service-error "get-host-by-address"))))
  236. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  237. ;;;
  238. ;;; SOCKET BASE CLASS AND GENERIC FUNCTIONS
  239. ;;;
  240. (defclass socket ()
  241. ((file-descriptor :initarg :descriptor
  242. :reader socket-file-descriptor)
  243. (family :initform (error "No socket family")
  244. :reader socket-family)
  245. (protocol :initarg :protocol
  246. :reader socket-protocol
  247. :documentation "Protocol used by the socket. If a
  248. keyword, the symbol-name of the keyword will be passed to
  249. GET-PROTOCOL-BY-NAME downcased, and the returned value used as
  250. protocol. Other values are used as-is.")
  251. (type :initarg :type
  252. :reader socket-type
  253. :initform :stream
  254. :documentation "Type of the socket: :STREAM or :DATAGRAM.")
  255. (stream)
  256. #+:wsock
  257. (non-blocking-p :initform nil))
  258. (:documentation "Common base class of all sockets, not meant to be
  259. directly instantiated."))
  260. (defmethod print-object ((object socket) stream)
  261. (print-unreadable-object (object stream :type t :identity t)
  262. (princ "descriptor " stream)
  263. (princ (slot-value object 'file-descriptor) stream)))
  264. (defmethod shared-initialize :after ((socket socket) slot-names
  265. &key protocol type
  266. &allow-other-keys)
  267. (let* ((proto-num
  268. (cond ((and protocol (keywordp protocol))
  269. (get-protocol-by-name (string-downcase (symbol-name protocol))))
  270. (protocol protocol)
  271. (t 0)))
  272. (fd (or (and (slot-boundp socket 'file-descriptor)
  273. (socket-file-descriptor socket))
  274. #+:wsock
  275. (and (member (socket-family socket) (list +af-named-pipe+ +af-local+)) 0)
  276. (ff-socket (socket-family socket)
  277. (ecase (or type
  278. (socket-type socket))
  279. ((:datagram) (c-constant "SOCK_DGRAM"))
  280. ((:stream) (c-constant "SOCK_STREAM")))
  281. proto-num))))
  282. (if (= fd -1) (socket-error "socket"))
  283. (setf (slot-value socket 'file-descriptor) fd
  284. (slot-value socket 'protocol) proto-num)
  285. #+ ignore
  286. (sb-ext:finalize socket (lambda () (sockint::close fd)))))
  287. ;; Generics
  288. (defgeneric socket-bind (socket &rest address)
  289. (:documentation "Bind SOCKET to ADDRESS, which may vary according to
  290. socket family. For the INET family, pass ADDRESS and PORT as two
  291. arguments; for FILE address family sockets, pass the filename string.
  292. See also bind(2)"))
  293. (defgeneric socket-accept (socket)
  294. (:documentation "Perform the accept(2) call, returning a
  295. newly-created connected socket and the peer address as multiple
  296. values"))
  297. (defgeneric socket-connect (socket &rest address)
  298. (:documentation "Perform the connect(2) call to connect SOCKET to a
  299. remote PEER. No useful return value."))
  300. (defgeneric socket-peername (socket)
  301. (:documentation "Return the socket's peer; depending on the address
  302. family this may return multiple values"))
  303. (defgeneric socket-name (socket)
  304. (:documentation "Return the address (as vector of bytes) and port
  305. that the socket is bound to, as multiple values."))
  306. (defgeneric socket-listen (socket backlog)
  307. (:documentation "Mark SOCKET as willing to accept incoming connections. BACKLOG
  308. defines the maximum length that the queue of pending connections may
  309. grow to before new connection attempts are refused. See also listen(2)"))
  310. (defgeneric socket-receive (socket buffer length
  311. &key
  312. oob peek waitall element-type)
  313. (:documentation "Read LENGTH octets from SOCKET into BUFFER (or a freshly-consed buffer if
  314. NIL), using recvfrom(2). If LENGTH is NIL, the length of BUFFER is
  315. used, so at least one of these two arguments must be non-NIL. If
  316. BUFFER is supplied, it had better be of an element type one octet wide.
  317. Returns the buffer, its length, and the address of the peer
  318. that sent it, as multiple values. On datagram sockets, sets MSG_TRUNC
  319. so that the actual packet length is returned even if the buffer was too
  320. small"))
  321. (defgeneric socket-send (socket buffer length
  322. &key
  323. address external-format oob eor dontroute dontwait
  324. nosignal confirm more)
  325. (:documentation "Send length octets from buffer into socket, using sendto(2).
  326. If buffer is a string, it will converted to octets according to external-format&
  327. If length is nil, the length of the octet buffer is used. The format of address
  328. depends on the socket type (for example for inet domain sockets it would be a
  329. list of an ip address and a port). If no socket address is provided, send(2)
  330. will be called instead. Returns the number of octets written."))
  331. (defgeneric socket-close (socket)
  332. (:documentation "Close SOCKET. May throw any kind of error that write(2) would have
  333. thrown. If SOCKET-MAKE-STREAM has been called, calls CLOSE on that
  334. stream instead"))
  335. (defgeneric socket-make-stream (socket &rest args)
  336. (:documentation "Find or create a STREAM that can be used for IO
  337. on SOCKET (which must be connected). ARGS are passed onto
  338. SB-SYS:MAKE-FD-STREAM."))
  339. (defgeneric non-blocking-mode (socket)
  340. (:documentation "Is SOCKET in non-blocking mode?"))
  341. (defgeneric (setf non-blocking-mode) (non-blocking-p socket)
  342. (:documentation "Put SOCKET in non-blocking mode - or not, according to NON-BLOCKING-P"))
  343. (defgeneric socket-close-low-level (socket)
  344. (:documentation "Close SOCKET at low level. Do not use directly."))
  345. ;; Methods
  346. (defmethod socket-listen ((socket socket) backlog)
  347. (let ((r (ff-listen (socket-file-descriptor socket) backlog)))
  348. (if (= r -1)
  349. (socket-error "listen"))))
  350. (defmethod socket-close-low-level ((socket socket))
  351. (ff-close (socket-file-descriptor socket)))
  352. (defmethod socket-close ((socket socket))
  353. ;; the close(2) manual page has all kinds of warning about not
  354. ;; checking the return value of close, on the grounds that an
  355. ;; earlier write(2) might have returned successfully w/o actually
  356. ;; writing the stuff to disk. It then goes on to define the only
  357. ;; possible error return as EBADF (fd isn't a valid open file
  358. ;; descriptor). Presumably this is an oversight and we could also
  359. ;; get anything that write(2) would have given us.
  360. ;; note that if you have a socket _and_ a stream on the same fd,
  361. ;; the socket will avoid doing anything to close the fd in case
  362. ;; the stream has done it already - if so, it may have been
  363. ;; reassigned to some other file, and closing it would be bad
  364. (let ((fd (socket-file-descriptor socket)))
  365. (unless (eql fd -1) ; already closed
  366. (cond ((slot-boundp socket 'stream)
  367. (let ((stream (slot-value socket 'stream)))
  368. #+threads
  369. (close (two-way-stream-input-stream stream))
  370. #+threads
  371. (close (two-way-stream-output-stream stream))
  372. #-threads
  373. (close stream)) ;; closes fd indirectly
  374. (slot-makunbound socket 'stream))
  375. ((= (socket-close-low-level socket) -1)
  376. (socket-error "close")))
  377. (setf (slot-value socket 'file-descriptor) -1))))
  378. (ffi::clines "
  379. static void *
  380. safe_buffer_pointer(cl_object x, cl_index size)
  381. {
  382. cl_type t = type_of(x);
  383. int ok = 0;
  384. if (t == t_base_string) {
  385. ok = (size <= x->base_string.dim);
  386. } else if (t == t_vector) {
  387. cl_elttype aet = (cl_elttype)x->vector.elttype;
  388. if (aet == aet_b8 || aet == aet_i8 || aet == aet_bc) {
  389. ok = (size <= x->vector.dim);
  390. } else if (aet == aet_fix || aet == aet_index) {
  391. cl_index divisor = sizeof(cl_index);
  392. size = (size + divisor - 1) / divisor;
  393. ok = (size <= x->vector.dim);
  394. }
  395. }
  396. if (!ok) {
  397. FEerror(\"Lisp object is not a valid socket buffer: ~A\", 1, x);
  398. }
  399. return (void *)x->vector.self.t;
  400. }
  401. ")
  402. ;; FIXME: How bad is manipulating fillp directly?
  403. (defmethod socket-receive ((socket socket) buffer length
  404. &key oob peek waitall element-type)
  405. (unless (or buffer length) (error "You have to supply either buffer or length!"))
  406. (let ((buffer (or buffer (make-array length :element-type element-type)))
  407. (length (or length (length buffer)))
  408. (fd (socket-file-descriptor socket)))
  409. (multiple-value-bind (len-recv errno)
  410. (c-inline (fd buffer length
  411. oob peek waitall)
  412. (:int :object :int :bool :bool :bool)
  413. (values :long :int)
  414. "
  415. {
  416. int flags = ( #3 ? MSG_OOB : 0 ) |
  417. ( #4 ? MSG_PEEK : 0 ) |
  418. ( #5 ? MSG_WAITALL : 0 );
  419. cl_type type = type_of(#1);
  420. ssize_t len;
  421. ecl_disable_interrupts();
  422. len = recvfrom(#0, wincoerce(char*, safe_buffer_pointer(#1, #2)),
  423. #2, flags, NULL,NULL);
  424. ecl_enable_interrupts();
  425. if (len >= 0) {
  426. if (type == t_vector) { #1->vector.fillp = len; }
  427. else if (type == t_base_string) { #1->base_string.fillp = len; }
  428. }
  429. @(return 0) = len;
  430. @(return 1) = errno;
  431. }
  432. "
  433. :one-liner nil)
  434. (cond ((and (= len-recv -1)
  435. (member errno (list +eagain+ +eintr+)))
  436. nil)
  437. ((= len-recv -1)
  438. (socket-error "receive"))
  439. (t
  440. (values buffer len-recv))))))
  441. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  442. ;;;
  443. ;;; INET SOCKETS
  444. ;;;
  445. ;; We could refactor a lot here, if we pass sockaddr_foo structs around in Lisp. But
  446. ;; I do not feel comfortable with that.
  447. (defun get-protocol-by-name (string-or-symbol)
  448. "Calls getprotobyname"
  449. (let ((string (string string-or-symbol)))
  450. (c-inline (string) (:cstring) :int
  451. "{
  452. struct protoent *pe;
  453. pe = getprotobyname(#0);
  454. @(return 0) = pe ? pe->p_proto : -1;
  455. }
  456. ")))
  457. (defun make-inet-address (dotted-quads)
  458. "Return a vector of octets given a string DOTTED-QUADS in the format
  459. \"127.0.0.1\""
  460. (map 'vector
  461. #'parse-integer
  462. (split dotted-quads nil '(#\.))))
  463. (defclass inet-socket (socket)
  464. ((family :initform +af-inet+))
  465. (:documentation "Class representing TCP and UDP sockets.
  466. Examples:
  467. (make-instance 'inet-socket :type :stream :protocol :tcp)
  468. (make-instance 'inet-socket :type :datagram :protocol :udp)
  469. "))
  470. (defun make-inet-socket (type protocol)
  471. "Make an INET socket. Deprecated in favour of make-instance"
  472. (make-instance 'inet-socket :type type :protocol protocol))
  473. (Clines
  474. "
  475. static void fill_inet_sockaddr(struct sockaddr_in *sockaddr, int port,
  476. int a1, int a2, int a3, int a4)
  477. {
  478. #if defined(_MSC_VER) || defined(mingw32)
  479. memset(sockaddr,0,sizeof(struct sockaddr_in));
  480. #else
  481. bzero(sockaddr,sizeof(struct sockaddr_in));
  482. #endif
  483. sockaddr->sin_family = AF_INET;
  484. sockaddr->sin_port = htons(port);
  485. sockaddr->sin_addr.s_addr= htonl((uint32_t)a1<<24 | (uint32_t)a2<<16 | (uint32_t)a3<<8 | (uint32_t)a4) ;
  486. }
  487. ")
  488. (defmethod socket-bind ((socket inet-socket) &rest address)
  489. (assert (= 2 (length address)) (address) "Socket-bind needs three parameters for inet sockets.")
  490. (let ((ip (first address))
  491. (port (second address)))
  492. (if (= -1
  493. (c-inline (port (aref ip 0) (aref ip 1) (aref ip 2) (aref ip 3)
  494. (socket-file-descriptor socket))
  495. (:int :int :int :int :int :int)
  496. :int
  497. "
  498. {
  499. struct sockaddr_in sockaddr;
  500. int output;
  501. ecl_disable_interrupts();
  502. fill_inet_sockaddr(&sockaddr, #0, #1, #2, #3, #4);
  503. output = bind(#5,(struct sockaddr*)&sockaddr, sizeof(struct sockaddr_in));
  504. ecl_enable_interrupts();
  505. @(return) = output;
  506. }"
  507. :side-effects t))
  508. (socket-error "bind"))))
  509. (defmethod socket-accept ((socket inet-socket))
  510. (let ((sfd (socket-file-descriptor socket)))
  511. (multiple-value-bind (fd vector port)
  512. (c-inline (sfd) (:int) (values :int :object :int)
  513. "{
  514. struct sockaddr_in sockaddr;
  515. socklen_t addr_len = (socklen_t)sizeof(struct sockaddr_in);
  516. int new_fd;
  517. ecl_disable_interrupts();
  518. new_fd = accept(#0, (struct sockaddr*)&sockaddr, &addr_len);
  519. ecl_enable_interrupts();
  520. @(return 0) = new_fd;
  521. @(return 1) = ECL_NIL;
  522. @(return 2) = 0;
  523. if (new_fd != -1) {
  524. uint32_t ip = ntohl(sockaddr.sin_addr.s_addr);
  525. uint16_t port = ntohs(sockaddr.sin_port);
  526. cl_object vector = cl_make_array(1,MAKE_FIXNUM(4));
  527. ecl_aset(vector,0, MAKE_FIXNUM( ip>>24 ));
  528. ecl_aset(vector,1, MAKE_FIXNUM( (ip>>16) & 0xFF));
  529. ecl_aset(vector,2, MAKE_FIXNUM( (ip>>8) & 0xFF));
  530. ecl_aset(vector,3, MAKE_FIXNUM( ip & 0xFF ));
  531. @(return 1) = vector;
  532. @(return 2) = port;
  533. }
  534. }")
  535. (cond
  536. ((= fd -1)
  537. (socket-error "accept"))
  538. (t
  539. (values
  540. (make-instance (class-of socket)
  541. :type (socket-type socket)
  542. :protocol (socket-protocol socket)
  543. :descriptor fd)
  544. vector
  545. port))))))
  546. (defmethod socket-connect ((socket inet-socket) &rest address)
  547. (let ((ip (first address))
  548. (port (second address)))
  549. (if (= -1
  550. (c-inline (port (aref ip 0) (aref ip 1) (aref ip 2) (aref ip 3)
  551. (socket-file-descriptor socket))
  552. (:int :int :int :int :int :int)
  553. :int
  554. "
  555. {
  556. struct sockaddr_in sockaddr;
  557. int output;
  558. ecl_disable_interrupts();
  559. fill_inet_sockaddr(&sockaddr, #0, #1, #2, #3, #4);
  560. output = connect(#5,(struct sockaddr*)&sockaddr, sizeof(struct sockaddr_in));
  561. ecl_enable_interrupts();
  562. @(return) = output;
  563. }"))
  564. (socket-error "connect"))))
  565. (defmethod socket-peername ((socket inet-socket))
  566. (let* ((vector (make-array 4))
  567. (fd (socket-file-descriptor socket))
  568. (port (c-inline (fd vector) (:int t) :int
  569. "@01;{
  570. struct sockaddr_in name;
  571. socklen_t len = sizeof(struct sockaddr_in);
  572. int ret;
  573. ecl_disable_interrupts();
  574. ret = getpeername(#0,(struct sockaddr*)&name,&len);
  575. ecl_enable_interrupts();
  576. if (ret == 0) {
  577. uint32_t ip = ntohl(name.sin_addr.s_addr);
  578. uint16_t port = ntohs(name.sin_port);
  579. ecl_aset(#1,0, MAKE_FIXNUM( ip>>24 ));
  580. ecl_aset(#1,1, MAKE_FIXNUM( (ip>>16) & 0xFF));
  581. ecl_aset(#1,2, MAKE_FIXNUM( (ip>>8) & 0xFF));
  582. ecl_aset(#1,3, MAKE_FIXNUM( ip & 0xFF ));
  583. @(return) = port;
  584. } else {
  585. @(return) = -1;
  586. }
  587. }")))
  588. (if (>= port 0)
  589. (values vector port)
  590. (socket-error "getpeername"))))
  591. (defmethod socket-name ((socket inet-socket))
  592. (let* ((vector (make-array 4))
  593. (fd (socket-file-descriptor socket))
  594. (port (c-inline (fd vector) (:int t) :int
  595. "@01;{
  596. struct sockaddr_in name;
  597. socklen_t len = sizeof(struct sockaddr_in);
  598. int ret;
  599. ecl_disable_interrupts();
  600. ret = getsockname(#0,(struct sockaddr*)&name,&len);
  601. ecl_enable_interrupts();
  602. if (ret == 0) {
  603. uint32_t ip = ntohl(name.sin_addr.s_addr);
  604. uint16_t port = ntohs(name.sin_port);
  605. ecl_aset(#1,0, MAKE_FIXNUM( ip>>24 ));
  606. ecl_aset(#1,1, MAKE_FIXNUM( (ip>>16) & 0xFF));
  607. ecl_aset(#1,2, MAKE_FIXNUM( (ip>>8) & 0xFF));
  608. ecl_aset(#1,3, MAKE_FIXNUM( ip & 0xFF ));
  609. @(return) = port;
  610. } else {
  611. @(return) = -1;
  612. }
  613. }")))
  614. (if (>= port 0)
  615. (values vector port)
  616. (socket-error "getsockname"))))
  617. #+:wsock
  618. (defmethod socket-close-low-level ((socket inet-socket))
  619. (ff-closesocket (socket-file-descriptor socket)))
  620. (defmethod socket-send ((socket socket) buffer length
  621. &key address external-format oob eor dontroute dontwait nosignal confirm more)
  622. (declare (ignore external-format more))
  623. (assert (or (stringp buffer)
  624. (typep buffer 'vector)))
  625. (let (;eh, here goes string->octet convertion...
  626. ;When will ecl support Unicode?
  627. (length (or length (length buffer)))
  628. (fd (socket-file-descriptor socket)))
  629. (let ((len-sent
  630. (if address
  631. (progn
  632. (assert (= 2 (length address)))
  633. (c-inline (fd buffer length
  634. (second address)
  635. (aref (first address) 0)
  636. (aref (first address) 1)
  637. (aref (first address) 2)
  638. (aref (first address) 3)
  639. oob eor dontroute dontwait nosignal confirm)
  640. (:int :object :int
  641. :int :int :int :int :int
  642. :bool :bool :bool :bool :bool :bool)
  643. :long
  644. "
  645. {
  646. int sock = #0;
  647. int length = #2;
  648. void *buffer = safe_buffer_pointer(#1, length);
  649. int flags = ( #8 ? MSG_OOB : 0 ) |
  650. ( #9 ? MSG_EOR : 0 ) |
  651. ( #a ? MSG_DONTROUTE : 0 ) |
  652. ( #b ? MSG_DONTWAIT : 0 ) |
  653. ( #c ? MSG_NOSIGNAL : 0 ) |
  654. ( #d ? MSG_CONFIRM : 0 );
  655. cl_type type = type_of(#1);
  656. struct sockaddr_in sockaddr;
  657. ssize_t len;
  658. ecl_disable_interrupts();
  659. fill_inet_sockaddr(&sockaddr, #3, #4, #5, #6, #7);
  660. ##if (MSG_NOSIGNAL == 0) && defined(SO_NOSIGPIPE)
  661. {
  662. int sockopt = #c;
  663. setsockopt(#0,SOL_SOCKET,SO_NOSIGPIPE,
  664. wincoerce(char *,&sockopt),
  665. sizeof(int));
  666. }
  667. ##endif
  668. len = sendto(sock, wincoerce(char *,buffer),
  669. length, flags,(struct sockaddr*)&sockaddr,
  670. sizeof(struct sockaddr_in));
  671. ecl_enable_interrupts();
  672. @(return) = len;
  673. }
  674. "
  675. :one-liner nil))
  676. (c-inline (fd buffer length
  677. oob eor dontroute dontwait nosignal confirm)
  678. (:int :object :int
  679. :bool :bool :bool :bool :bool :bool)
  680. :long
  681. "
  682. {
  683. int sock = #0;
  684. int length = #2;
  685. void *buffer = safe_buffer_pointer(#1, length);
  686. int flags = ( #3 ? MSG_OOB : 0 ) |
  687. ( #4 ? MSG_EOR : 0 ) |
  688. ( #5 ? MSG_DONTROUTE : 0 ) |
  689. ( #6 ? MSG_DONTWAIT : 0 ) |
  690. ( #7 ? MSG_NOSIGNAL : 0 ) |
  691. ( #8 ? MSG_CONFIRM : 0 );
  692. cl_type type = type_of(#1);
  693. ssize_t len;
  694. ecl_disable_interrupts();
  695. ##if (MSG_NOSIGNAL == 0) && defined(SO_NOSIGPIPE)
  696. {
  697. int sockopt = #7;
  698. setsockopt(#0,SOL_SOCKET,SO_NOSIGPIPE,
  699. wincoerce(char *,&sockopt),
  700. sizeof(int));
  701. }
  702. ##endif
  703. len = send(sock, wincoerce(char *, buffer), length, flags);
  704. ecl_enable_interrupts();
  705. @(return) = len;
  706. }
  707. "
  708. :one-liner nil))))
  709. (if (= len-sent -1)
  710. (socket-error "send")
  711. len-sent))))
  712. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  713. ;;;
  714. ;;; UNIX SOCKETS
  715. ;;;
  716. #-:wsock
  717. (progn
  718. (defclass local-socket (socket)
  719. ((family :initform +af-local+))
  720. (:documentation "Class representing local domain (AF_LOCAL) sockets,
  721. also known as unix-domain sockets."))
  722. (defmethod socket-bind ((socket local-socket) &rest address)
  723. (assert (= 1 (length address)) (address) "Socket-bind needs two parameters for local sockets.")
  724. (let ((name (first address))
  725. (fd (socket-file-descriptor socket))
  726. (family (socket-family socket)))
  727. (if (= -1
  728. (c-inline (fd name family) (:int :cstring :int) :int
  729. "
  730. {
  731. struct sockaddr_un sockaddr;
  732. size_t size;
  733. int output;
  734. ##ifdef BSD
  735. sockaddr.sun_len = sizeof(struct sockaddr_un);
  736. ##endif
  737. sockaddr.sun_family = #2;
  738. strncpy(sockaddr.sun_path,#1,sizeof(sockaddr.sun_path));
  739. sockaddr.sun_path[sizeof(sockaddr.sun_path)-1] = 0;
  740. ecl_disable_interrupts();
  741. output = bind(#0,(struct sockaddr*)&sockaddr, sizeof(struct sockaddr_un));
  742. ecl_enable_interrupts();
  743. @(return) = output;
  744. }"))
  745. (socket-error "bind"))))
  746. (defmethod socket-accept ((socket local-socket))
  747. (multiple-value-bind (fd name)
  748. (c-inline ((socket-file-descriptor socket)) (:int) (values :int :object)
  749. "{
  750. struct sockaddr_un sockaddr;
  751. socklen_t addr_len = (socklen_t)sizeof(struct sockaddr_un);
  752. int new_fd;
  753. ecl_disable_interrupts();
  754. new_fd = accept(#0, (struct sockaddr *)&sockaddr, &addr_len);
  755. ecl_enable_interrupts();
  756. @(return 0) = new_fd;
  757. @(return 1) = (new_fd == -1) ? ECL_NIL : make_base_string_copy(sockaddr.sun_path);
  758. }")
  759. (cond
  760. ((= fd -1)
  761. (socket-error "accept"))
  762. (t
  763. (values
  764. (make-instance (class-of socket)
  765. :type (socket-type socket)
  766. :protocol (socket-protocol socket)
  767. :descriptor fd)
  768. name)))))
  769. (defmethod socket-connect ((socket local-socket) &rest address)
  770. (assert (= 1 (length address)) (address) "Socket-connect needs two parameters for local sockets.")
  771. (let ((path (first address))
  772. (fd (socket-file-descriptor socket))
  773. (family (socket-family socket)))
  774. (if (= -1
  775. (c-inline (fd family path) (:int :int :cstring) :int
  776. "
  777. {
  778. struct sockaddr_un sockaddr;
  779. int output;
  780. ##ifdef BSD
  781. sockaddr.sun_len = sizeof(struct sockaddr_un);
  782. ##endif
  783. sockaddr.sun_family = #1;
  784. strncpy(sockaddr.sun_path,#2,sizeof(sockaddr.sun_path));
  785. sockaddr.sun_path[sizeof(sockaddr.sun_path)-1] = 0;
  786. ecl_disable_interrupts();
  787. output = connect(#0,(struct sockaddr*)&sockaddr, sizeof(struct sockaddr_un));
  788. ecl_enable_interrupts();
  789. @(return) = output;
  790. }"))
  791. (socket-error "connect"))))
  792. (defmethod socket-peername ((socket local-socket))
  793. (let* ((fd (socket-file-descriptor socket))
  794. (peer (c-inline (fd) (:int) t
  795. "
  796. {
  797. struct sockaddr_un name;
  798. socklen_t len = sizeof(struct sockaddr_un);
  799. int ret;
  800. ecl_disable_interrupts();
  801. ret = getpeername(#0,(struct sockaddr*)&name,&len);
  802. ecl_enable_interrupts();
  803. if (ret == 0) {
  804. @(return) = make_base_string_copy(name.sun_path);
  805. } else {
  806. @(return) = ECL_NIL;
  807. }
  808. }")))
  809. (if peer
  810. peer
  811. (socket-error "getpeername"))))
  812. ) ;#-:wsock
  813. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  814. ;;;
  815. ;;; UNIX SOCKETS [WIN32, using the cygwin way]
  816. ;;;
  817. #+:wsock
  818. (progn
  819. (defclass local-socket (socket)
  820. ((family :initform +af-local+)
  821. proxy-socket local-path)
  822. (:documentation "Class representing local domain (AF_LOCAL) sockets,
  823. also known as unix-domain sockets."))
  824. (defmethod initialize-instance :after ((socket local-socket) &rest args)
  825. (declare (ignore args))
  826. (with-slots (protocol type) socket
  827. (setf (slot-value socket 'proxy-socket)
  828. (make-instance 'inet-socket :protocol protocol :type type))))
  829. (defmethod socket-bind ((socket local-socket) &rest address)
  830. (assert (= 1 (length address)) (address) "Socket-bind needs two parameters for local sockets.")
  831. (with-slots (proxy-socket local-path) socket
  832. (socket-bind proxy-socket #(127 0 0 1) 0)
  833. (multiple-value-bind (ip port) (socket-peername proxy-socket)
  834. (handler-case
  835. (with-open-file (fd (first address) :if-exists :error :if-does-not-exist :create :direction :output)
  836. (format fd "!<socket >~D 00000000-00000000-00000000-00000000" port))
  837. (file-error ()
  838. (socket-close proxy-socket)
  839. (c-inline () () nil "WSASetLastError(WSAEADDRINUSE)" :one-liner t)
  840. (socket-error "socket-bind")))
  841. (setf local-path (first address))
  842. socket)))
  843. (defmethod socket-accept ((socket local-socket))
  844. (multiple-value-bind (new-socket addr) (socket-accept (slot-value socket 'proxy-socket))
  845. (values socket (slot-value socket 'local-path))))
  846. (defmethod socket-connect ((socket local-socket) &rest address)
  847. (assert (= 1 (length address)) (address) "Socket-connect needs two parameters for local sockets.")
  848. (with-slots (proxy-socket local-path) socket
  849. (handler-case
  850. (with-open-file (fd (first address) :if-does-not-exist :error :direction :input)
  851. (let ((buf (make-string 128)) port)
  852. (read-sequence buf fd)
  853. (unless (and (string-equal "!<socket >" (subseq buf 0 10))
  854. (typep (setq port (read-from-string (subseq buf 10) nil 'eof)) '(integer 0 65535)))
  855. (c-inline () () nil "WSASetLastError(WSAEFAULT)" :one-liner t)
  856. (socket-error "connect"))
  857. (prog1
  858. (socket-connect proxy-socket #(127 0 0 1) port)
  859. (setf local-path (first address)))))
  860. (file-error ()
  861. (socket-error "connect")))))
  862. (defmethod socket-peername ((socket local-socket))
  863. (unless (slot-boundp socket 'local-path)
  864. (c-inline () () nil "WSASetLastError(WSAENOTCONN)" :one-liner t)
  865. (socket-error "socket-peername"))
  866. (slot-value socket 'local-path))
  867. (defmethod socket-close ((socket local-socket))
  868. (socket-close (slot-value socket 'proxy-socket))
  869. (slot-makunbound socket 'local-path))
  870. (defmethod socket-make-stream ((socket local-socket) &rest args)
  871. (apply #'socket-make-stream (cons (slot-value socket 'proxy-socket) args)))
  872. (defmethod non-blocking-mode ((socket local-socket))
  873. (non-blocking-mode (slot-value socket 'proxy-socket)))
  874. (defmethod (setf non-blocking-mode) (non-blocking-p (socket local-socket))
  875. (setf (non-blocking-mode (slot-value socket 'proxy-socket)) non-blocking-p))
  876. ) ;#+:wsock
  877. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  878. ;;;
  879. ;;; NAMED PIPE SOCKETS [WIN32]
  880. ;;;
  881. #+:wsock
  882. (progn
  883. (defclass named-pipe-socket (socket)
  884. ((family :initform +af-named-pipe+)
  885. (pipe-name :initarg :pipe-name))
  886. (:documentation "Class representing Win32 named pipe, using a socket-like interface."))
  887. (defmethod socket-bind ((socket named-pipe-socket) &rest address)
  888. (assert (= 1 (length address)) (address) "Socket-bind needs two parameters for local sockets.")
  889. (let* ((pipe-name (concatenate 'string "\\\\.\\pipe\\" (first address)))
  890. (hnd (c-inline (pipe-name) (:cstring) :int
  891. "
  892. {
  893. HANDLE hnd;
  894. ecl_disable_interrupts();
  895. hnd = CreateNamedPipe(
  896. #0,
  897. PIPE_ACCESS_DUPLEX,
  898. PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
  899. PIPE_UNLIMITED_INSTANCES,
  900. 4096,
  901. 4096,
  902. NMPWAIT_USE_DEFAULT_WAIT,
  903. NULL);
  904. ecl_enable_interrupts();
  905. if (hnd == INVALID_HANDLE_VALUE)
  906. @(return) = -1;
  907. else
  908. @(return) = _open_osfhandle((intptr_t)hnd, O_RDWR);
  909. }")))
  910. (when (= hnd -1)
  911. (socket-error "CreateNamedPipe"))
  912. (setf (slot-value socket 'pipe-name) pipe-name)
  913. (setf (slot-value socket 'file-descriptor) hnd)))
  914. (defmethod socket-accept ((socket named-pipe-socket))
  915. (let* ((fd (socket-file-descriptor socket))
  916. (afd (c-inline (fd) (:int) :int
  917. "
  918. {
  919. HANDLE hnd = (HANDLE)_get_osfhandle(#0), dupHnd;
  920. ecl_disable_interrupts();
  921. if (ConnectNamedPipe(hnd, NULL) != 0 || GetLastError() == ERROR_PIPE_CONNECTED) {
  922. @(return) = #0;
  923. } else
  924. @(return) = -1;
  925. ecl_enable_interrupts();
  926. }"
  927. :one-liner nil)))
  928. (cond
  929. ((= afd -1)
  930. (socket-error "accept"))
  931. (t
  932. ;; rebind the socket to create a new named pipe instance in the server
  933. (socket-bind socket (subseq (slot-value socket 'pipe-name) 9))
  934. (values
  935. (make-instance (class-of socket)
  936. :type (socket-type socket)
  937. :protocol (socket-protocol socket)
  938. :descriptor afd
  939. :pipe-name (slot-value socket 'pipe-name))
  940. (slot-value socket 'pipe-name))))))
  941. (defmethod socket-connect ((socket named-pipe-socket) &rest address)
  942. (assert (= 1 (length address)) (address) "Socket-connect needs two parameters for local sockets.")
  943. (let* ((path (first address))
  944. (pipe-name (concatenate 'string "\\\\.\\pipe\\" path)))
  945. (if (= -1
  946. (setf (slot-value socket 'file-descriptor)
  947. (c-inline (pipe-name) (:cstring) :int
  948. "
  949. {
  950. HANDLE hnd;
  951. ecl_disable_interrupts();
  952. hnd = CreateFile(
  953. #0,
  954. GENERIC_READ | GENERIC_WRITE,
  955. 0,
  956. NULL,
  957. OPEN_EXISTING,
  958. 0,
  959. NULL);
  960. if (hnd == INVALID_HANDLE_VALUE)
  961. @(return) = -1;
  962. else
  963. @(return) = _open_osfhandle((intptr_t)hnd, O_RDWR);
  964. ecl_enable_interrupts();
  965. }")))
  966. (socket-error "connect")
  967. (setf (slot-value socket 'pipe-name) pipe-name))))
  968. (defmethod socket-peername ((socket named-pipe-socket))
  969. (slot-value socket 'pipe-name))
  970. (defmethod (setf non-blocking-mode) (non-blocking-p (socket named-pipe-socket))
  971. (let ((fd (socket-file-descriptor socket)))
  972. (if (= 0
  973. (c-inline (fd non-blocking-p) (:int t) :int
  974. "
  975. {
  976. DWORD mode = PIPE_READMODE_BYTE | (#1 == ECL_T ? PIPE_NOWAIT : PIPE_WAIT);
  977. HANDLE h = (HANDLE)_get_osfhandle(#0);
  978. ecl_disable_interrupts();
  979. @(return) = SetNamedPipeHandleState(h, &mode, NULL, NULL);
  980. ecl_enable_interrupts();
  981. }"
  982. :one-liner nil))
  983. (socket-error "SetNamedPipeHandleState")
  984. (setf (slot-value socket 'non-blocking-p) non-blocking-p))))
  985. (defmethod socket-close ((socket named-pipe-socket))
  986. (let ((fd (socket-file-descriptor socket)))
  987. (unless (c-inline (fd) (:int) t
  988. "
  989. {
  990. DWORD flags;
  991. HANDLE h = (HANDLE)_get_osfhandle(#0);
  992. ecl_disable_interrupts();
  993. if (!GetNamedPipeInfo(h, &flags, NULL, NULL, NULL))
  994. @(return) = ECL_NIL;
  995. if (flags == PIPE_CLIENT_END || DisconnectNamedPipe(h))
  996. @(return) = ECL_T;
  997. else
  998. @(return) = ECL_NIL;
  999. ecl_enable_interrupts();
  1000. }"
  1001. :one-liner nil)
  1002. (socket-error "DisconnectNamedPipe"))
  1003. (call-next-method)))
  1004. ) ;#+:wsock
  1005. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1006. ;;;
  1007. ;;; NON-BLOCKING MODE
  1008. ;;;
  1009. (defmethod non-blocking-mode ((socket socket))
  1010. #-:wsock
  1011. (let ((fd (socket-file-descriptor socket)))
  1012. (not (zerop (c-inline (fd) (:int) :int "fcntl(#0,F_GETFL,NULL)&O_NONBLOCK" :one-liner t))))
  1013. #+:wsock
  1014. (slot-value socket 'non-blocking-p)
  1015. )
  1016. (defmethod (setf non-blocking-mode) (non-blocking-p (socket socket))
  1017. (let ((fd (socket-file-descriptor socket))
  1018. (nblock (if non-blocking-p 1 0)))
  1019. (if (= -1 (c-inline (fd nblock) (:int :int) :int
  1020. #+:wsock
  1021. "
  1022. {
  1023. int blocking_flag = (#1 ? 1 : 0);
  1024. ecl_disable_interrupts();
  1025. @(return) = ioctlsocket(#0, FIONBIO, (u_long*)&blocking_flag);
  1026. ecl_enable_interrupts();
  1027. }"
  1028. #-:wsock
  1029. "
  1030. {
  1031. int oldflags = fcntl(#0,F_GETFL,NULL);
  1032. int newflags = (oldflags & ~O_NONBLOCK) |
  1033. (#1 ? O_NONBLOCK : 0);
  1034. ecl_disable_interrupts();
  1035. @(return) = fcntl(#0,F_SETFL,newflags);
  1036. ecl_enable_interrupts();
  1037. }"))
  1038. (socket-error #-:wsock "fcntl" #+:wsock "ioctlsocket")
  1039. #-:wsock non-blocking-p
  1040. #+:wsock (setf (slot-value socket 'non-blocking-p) non-blocking-p))))
  1041. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1042. ;;;
  1043. ;;; STREAMS
  1044. ;;;
  1045. ;;; To actually read/write to/from the sockets, we use Lisp streams. The
  1046. ;;; following functions take care of building the streams. Fortunately
  1047. ;;; we do not have to care about things like buffering, binary streams,
  1048. ;;; etc, but we rather reuse the code from the C core. (For instance
  1049. ;;; the sockets will be closed upon garbage collection)
  1050. ;;;
  1051. (defun dup (fd)
  1052. (ffi:c-inline (fd) (:int) :int "dup(#0)" :one-liner t))
  1053. (defun make-stream-from-fd (fd mode &key buffering element-type (external-format :default)
  1054. (name "FD-STREAM"))
  1055. (assert (stringp name) (name) "name must be a string.")
  1056. (let* ((smm-mode (ecase mode
  1057. (:input (c-constant "ecl_smm_input"))
  1058. (:output (c-constant "ecl_smm_output"))
  1059. (:input-output (c-constant "ecl_smm_io"))
  1060. #+:wsock
  1061. (:input-wsock (c-constant "ecl_smm_input_wsock"))
  1062. #+:wsock
  1063. (:output-wsock (c-constant "ecl_smm_output_wsock"))
  1064. #+:wsock
  1065. (:input-output-wsock (c-constant "ecl_smm_io_wsock"))
  1066. ))
  1067. (external-format (unless (subtypep element-type 'integer) external-format))
  1068. (stream (ffi:c-inline (name fd smm-mode element-type external-format)
  1069. (t :int :int t t)
  1070. t
  1071. "
  1072. ecl_make_stream_from_fd(#0,#1,(enum ecl_smmode)#2,
  1073. ecl_normalize_stream_element_type(#3),
  1074. 0,#4)"
  1075. :one-liner t)))
  1076. (when buffering
  1077. (si::set-buffering-mode stream buffering))
  1078. stream))
  1079. (defun auto-close-two-way-stream (stream)
  1080. (declare (si::c-local))
  1081. (ffi:c-inline (stream) (t) :void
  1082. "(#0)->stream.flags |= ECL_STREAM_CLOSE_COMPONENTS"
  1083. :one-liner t))
  1084. (defun socket-make-stream-inner (fd input output buffering element-type external-format)
  1085. ;; In Unix we have to create one stream per channel. The reason is
  1086. ;; that buffered I/O is done using ANSI C FILEs which do not support
  1087. ;; concurrent reads and writes -- if one thread is listening to the
  1088. ;; FILE it blocks all output. The solution is to create a
  1089. ;; two-way-stream when both input and output are T, and force that
  1090. ;; stream to close its components (small hack in ECL). In Windows we
  1091. ;; do not have this problem because we do not know how to wrap a
  1092. ;; FILE around a socket.
  1093. (cond ((and input output)
  1094. #+wsock
  1095. (make-stream-from-fd fd :input-output-wsock
  1096. :buffering buffering
  1097. :element-type element-type
  1098. :external-format external-format)
  1099. #-wsock
  1100. (let* ((in (socket-make-stream-inner (dup fd) t nil buffering
  1101. element-type external-format))
  1102. (out (socket-make-stream-inner fd nil t buffering
  1103. element-type external-format))
  1104. (stream (make-two-way-stream in out)))
  1105. (auto-close-two-way-stream stream)
  1106. stream))
  1107. (input
  1108. (make-stream-from-fd fd #-wsock :input #+wsock :input-wsock
  1109. :buffering buffering
  1110. :element-type element-type
  1111. :external-format external-format))
  1112. (output
  1113. (make-stream-from-fd fd #-wsock :output #+wsock :output-wsock
  1114. :buffering buffering
  1115. :element-type element-type
  1116. :external-format external-format))
  1117. (t
  1118. (error "SOCKET-MAKE-STREAM: at least one of :INPUT or :OUTPUT has to be true."))))
  1119. (defmethod socket-make-stream ((socket socket)
  1120. &key (input nil input-p)
  1121. (output nil output-p)
  1122. (buffering :full)
  1123. (element-type 'base-char)
  1124. (external-format :default))
  1125. (let ((stream (and (slot-boundp socket 'stream)
  1126. (slot-value socket 'stream))))
  1127. (unless stream
  1128. ;; Complicated default logic for compatibility with previous releases
  1129. ;; should disappear soon. (FIXME!)
  1130. (unless (or input-p output-p)
  1131. (setf input t output t))
  1132. (setf stream (socket-make-stream-inner (socket-file-descriptor socket)
  1133. input output buffering element-type
  1134. external-format))
  1135. (setf (slot-value socket 'stream) stream)
  1136. #+ ignore
  1137. (sb-ext:cancel-finalization socket))
  1138. stream))
  1139. (defmethod ext::stream-fd ((socket socket))
  1140. (socket-file-descriptor socket))
  1141. #+:wsock
  1142. (defmethod socket-make-stream ((socket named-pipe-socket)
  1143. &key input output
  1144. (buffering :full) (external-format :default))
  1145. (let ((stream (and (slot-boundp socket 'stream)
  1146. (slot-value socket 'stream))))
  1147. (unless stream
  1148. (setf stream
  1149. (let* ((fd (socket-file-descriptor socket))
  1150. (in (make-stream-from-fd fd :smm-input buffering external-format))
  1151. (out (make-stream-from-fd fd :smm-output buffering external-format)))
  1152. (make-two-way-stream in out)))
  1153. (setf (slot-value socket 'stream) stream))
  1154. stream))
  1155. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1156. ;;;
  1157. ;;; ERROR HANDLING
  1158. ;;;
  1159. ;;; A plethora of conditions are defined below, almost one for each
  1160. ;;; possible error produced by the socket or DNS interface.
  1161. ;;;
  1162. #+:wsock
  1163. (defun get-win32-error-string (num)
  1164. (c-inline (num) (:int) t
  1165. "{char *lpMsgBuf;
  1166. cl_object msg;
  1167. ecl_disable_interrupts();
  1168. FormatMessage(
  1169. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  1170. NULL,
  1171. #0,
  1172. 0,
  1173. (LPTSTR)&lpMsgBuf,
  1174. 0,
  1175. NULL);
  1176. msg = make_base_string_copy(lpMsgBuf);
  1177. LocalFree(lpMsgBuf);
  1178. ecl_enable_interrupts();
  1179. @(return) = msg;}"
  1180. :one-liner nil))
  1181. ;;;
  1182. ;;; 1) SOCKET ERRORS
  1183. ;;;
  1184. (define-condition socket-error (error)
  1185. ((errno :initform nil
  1186. :initarg :errno
  1187. :reader socket-error-errno)
  1188. (symbol :initform nil :initarg :symbol :reader socket-error-symbol)
  1189. (syscall :initform "outer space" :initarg :syscall :reader socket-error-syscall))
  1190. (:report (lambda (c s)
  1191. (let ((num (socket-error-errno c)))
  1192. (format s "Socket error in \"~A\": ~A (~A)"
  1193. (socket-error-syscall c)
  1194. (or (socket-error-symbol c) (socket-error-errno c))
  1195. #+:wsock
  1196. (get-win32-error-string num)
  1197. #-:wsock
  1198. (c-inline (num) (:int) :cstring
  1199. "strerror(#0)" :one-liner t)))))
  1200. (:documentation "Common base class of socket related conditions."))
  1201. (defmacro define-socket-condition (symbol name)
  1202. `(let () ; Prevents evaluation of constant value at compilation time
  1203. (defconstant ,symbol (c-constant ,(symbol-name symbol)))
  1204. (define-condition ,name (socket-error)
  1205. ((symbol :reader socket-error-symbol :initform (quote ,symbol))))
  1206. (export ',name)
  1207. (push (cons ,symbol (quote ,name)) *conditions-for-errno*)))
  1208. (defparameter *conditions-for-errno* nil)
  1209. ;;; this needs the rest of the list adding to it, really. They also
  1210. ;;; need symbols to be added to constants.ccon
  1211. ;;; I haven't yet thought of a non-kludgey way of keeping all this in
  1212. ;;; the same place
  1213. #+:wsock
  1214. (Clines
  1215. "#define EADDRINUSE WSAEADDRINUSE"
  1216. "#define ECONNREFUS…

Large files files are truncated, but you can click here to view the full file