PageRenderTime 53ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/02-development/uni/mmiss/checker/src/src/share/base/socket-interface.lisp

https://bitbucket.org/jmelo_lyncode/thesis
Lisp | 985 lines | 531 code | 169 blank | 285 comment | 2 complexity | 7da237c346da51fcb7dc62336f7f4de0 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-3.0
  1. ;;; -*- Mode: Lisp; Base: 10; Syntax: Common-lisp; Package: INKA -*-
  2. ;;
  3. ;; ********************************************************************************************
  4. ;; *** This file is adapted from socket.lisp from the KEIM project written by Stephan Hess. ***
  5. ;; ********************************************************************************************
  6. ;;
  7. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;
  8. ;; ;;
  9. ;; Copyright (C) 1997 by AG Siekmann, Fachbereich Informatik, ;;
  10. ;; Universitaet des Saarlandes, Saarbruecken, Germany. ;;
  11. ;; All rights reserved. ;;
  12. ;; For information about this program, write to: ;;
  13. ;; KEIM Project ;;
  14. ;; AG Siekmann/FB Informatik ;;
  15. ;; Universitaet des Saarlandes ;;
  16. ;; Postfach 151150 ;;
  17. ;; D-66041 Saarbruecken ;;
  18. ;; Germany ;;
  19. ;; electronic mail: keim@cs.uni-sb.de ;;
  20. ;; ;;
  21. ;; The author makes no representations about the suitability of this ;;
  22. ;; software for any purpose. It is provided "AS IS" without express or ;;
  23. ;; implied warranty. In particular, it must be understood that this ;;
  24. ;; software is an experimental version, and is not suitable for use in ;;
  25. ;; any safety-critical application, and the author denies a license for ;;
  26. ;; such use. ;;
  27. ;; ;;
  28. ;; You may use, copy, modify and distribute this software for any ;;
  29. ;; noncommercial and non-safety-critical purpose. Use of this software ;;
  30. ;; in a commercial product is not included under this license. You must ;;
  31. ;; maintain this copyright statement in all copies of this software that ;;
  32. ;; you modify or distribute. ;;
  33. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;
  34. (in-package :inka)
  35. (require "service")
  36. ;; ---------------------------------------------------------------------------
  37. ;; Section 0 : foreign function definitions for socket implementation
  38. ;; ---------------------------------------------------------------------------
  39. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  40. (progn
  41. (ff:defforeign 'perror :arguments '(string) :pass-types '(:by-value))
  42. (ff:defforeign 'usocket)
  43. (ff:defforeign 'ubind :arguments '(integer) :pass-types '(:by-value))
  44. (ff:defforeign 'uaccept :arguments '(integer) :pass-types '(:by-value))
  45. (ff:defforeign 'uclose :arguments '(integer) :pass-types '(:by-value))
  46. (ff:defforeign 'uconnect :arguments '(string integer) :pass-types '(:by-value :by-value))
  47. (ff:defforeign 'uread :arguments '(integer integer string) :return-type :integer :pass-types '(:by-value :by-value :by-value))
  48. (ff:defforeign 'ureadwait :arguments '(integer integer string) :return-type :integer :pass-types '(:by-value :by-value :by-value))
  49. (ff:defforeign 'uwrite :arguments '(integer string) :pass-types '(:by-value :by-value))
  50. (ff:defforeign 'ugetpeername :arguments '(integer) :pass-types '(:by-value) :return-type :integer)
  51. (ff:defforeign 'uwritefile :arguments '(integer string))
  52. )
  53. ;; ---------------------------------------------------------------------------
  54. ;; Section 1 : The socket database.
  55. ;; ---------------------------------------------------------------------------
  56. (defvar socket*sockets
  57. ;;; Edited : 02.12.1998
  58. ;;; Authors : serge
  59. ;;; Descri. : a property list of symbolic socket names and sockets.
  60. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0)))) nil
  61. #+(or cmu (and allegro-version>= (version>= 5 0))) (make-hash-table) "A hashtable of symbolic socket names and sockets."
  62. )
  63. (defmacro socket=sockets ()
  64. ;;; Edited : 02.12.1998
  65. ;;; Authors : serge
  66. ;;; Input : /
  67. ;;; Effect : /
  68. ;;; Value : the actual value of `socket*sockets
  69. `socket*sockets)
  70. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  71. (defun socket-reset ()
  72. ;;; Edited : 03.12.1998
  73. ;;; Authors : serge
  74. ;;; Input : /
  75. ;;; Effect : resets all sockets. It closes any connected socket and removes the entries from the
  76. ;;; socket database.
  77. ;;; Value : undef.
  78. (setq socket*end-of-string (code-char 128))
  79. (mapcf #'(lambda (socketname socket)
  80. (when (not (equal socket 'unconnected))
  81. (socket-close socketname)))
  82. (socket=sockets))
  83. (setq socket*sockets nil))
  84. #+(or cmu (and allegro-version>= (version>= 5 0)))
  85. (defun socket-reset ()
  86. (maphash #'(lambda (socketname socket)
  87. (socket-close socketname))
  88. (socket=sockets))
  89. (clrhash (socket=sockets)))
  90. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  91. (defun socket=socketname.socket (socketname)
  92. ;;; Edited : 19. Feb 2001
  93. ;;; Authors : serge
  94. ;;; Input :
  95. ;;; Effect :
  96. ;;; Value :
  97. (getf (getf (socket=sockets) socketname) 'socket))
  98. #+(or cmu (and allegro-version>= (version>= 5 0)))
  99. (defun socket=socketname.socket (socketname)
  100. ;;; Edited : 19. Feb 2001
  101. ;;; Authors : serge
  102. ;;; Input :
  103. ;;; Effect :
  104. ;;; Value :
  105. (getf (gethash socketname (socket=sockets)) 'socket))
  106. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  107. (defun socket=socketname.buffer-string (socketname)
  108. ;;; Edited : 19. Feb 2001
  109. ;;; Authors : serge
  110. ;;; Input :
  111. ;;; Effect :
  112. ;;; Value :
  113. (getf (getf (socket=sockets) socketname) 'buffer-string))
  114. #+(or cmu (and allegro-version>= (version>= 5 0)))
  115. (defun socket=socketname.buffer-string (socketname)
  116. ;;; Edited : 19. Feb 2001
  117. ;;; Authors : serge
  118. ;;; Input :
  119. ;;; Effect :
  120. ;;; Value :
  121. (getf (gethash socketname (socket=sockets)) 'buffer-string))
  122. #+(and (not cmu) (and allegro-version>= (version>= 5 0)))
  123. (defun socket-find.socket (socketname)
  124. (socket=socketname.socket socketname))
  125. ;; ---------------------------------------------------------------------------
  126. ;; Section 2 : Defining/Undefining sockets.
  127. ;; ---------------------------------------------------------------------------
  128. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  129. (defun socket-define (socketname)
  130. ;;; Edited : 02.12.1998
  131. ;;; Authors : serge
  132. ;;; Input : an sexpr which is the symbolic name of a socket.
  133. ;;; Effect : creates an entry for this socket.
  134. ;;; Value : undef.
  135. (cond ((and socketname (null (getf socket*sockets socketname)))
  136. (setf (getf (getf socket*sockets socketname) 'port) nil)
  137. (setf (getf (getf socket*sockets socketname) 'socket) 'unconnected)
  138. (setf (getf (getf socket*sockets socketname) 'buffer-string) "")
  139. )
  140. ((null socketname)
  141. (format t "Invalid socket name ~A!" socketname))
  142. (T (print "Redefinition of existing socket-names is not allowed!")
  143. nil)))
  144. #+(or cmu (and allegro-version>= (version>= 5 0)))
  145. (defun socket-define (socketname)
  146. ;;; Edited : 20-SEP-2000
  147. ;;; Authors : pollet
  148. ;;; Input : An sexpr which is the symbolic name of a socket.
  149. ;;; Effect : Creates an entry for this socket.
  150. ;;; Value : T for success, NIL for failure.
  151. (cond ((and socketname (null (gethash socketname socket*sockets)))
  152. (setf (getf (gethash socketname socket*sockets) 'socket) 'unconnected)
  153. (setf (getf (gethash socketname socket*sockets) 'buffer-string) "")
  154. T)
  155. ((null socketname)
  156. (format t "Invalid socket name ~A!" socketname)
  157. nil)
  158. (T
  159. (print "Redefinition of existing socket-names is not allowed!")
  160. nil)))
  161. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  162. (defun socket-delete (socketname)
  163. ;;; Edited : 17.03.1997 01.12.1998
  164. ;;; Authors : hess serge
  165. ;;; Input : an sexpr defining a socket, i.e. a socketname
  166. ;;; Effect : deletes the socketname
  167. ;;; Value : /
  168. (let ((socket (getf (socket=sockets) socketname)))
  169. (cond ((and socket (equal (getf socket 'socket) 'unconnected))
  170. (remf socket*sockets socketname))
  171. ((null socket) (format t "Unknown socket ~A given to socket-undefine!" socketname) "")
  172. (t (format t "Socket ~A is still connected in socket-delete!" socketname) ""))))
  173. #+(or cmu (and allegro-version>= (version>= 5 0)))
  174. (defun socket-delete (socketname)
  175. ;;; Edited : 20-SEP-2000 14. Feb 2001
  176. ;;; Authors : Pollet serge
  177. ;;; Input : An sexpr defining a socket, i.e. a socketname.
  178. ;;; Effect : Deletes the socketname.
  179. ;;; Value : T for success, NIL for failure.
  180. (let ((socket (socket=socketname.socket socketname)))
  181. (cond ((and socket (equal socket 'unconnected))
  182. (remhash socketname socket*sockets)
  183. T)
  184. ((null socket)
  185. (format t "Unknown socket ~A given to socket-undefine!"
  186. socketname)
  187. nil
  188. )
  189. (t (format t "Socket ~A is still connected in socket-delete!" socketname)
  190. nil
  191. ))))
  192. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  193. (defun socket-active? (socketname)
  194. ;;; Edited : 11. Feb 1999
  195. ;;; Authors : serge
  196. ;;; Input : a socketname
  197. ;;; Effect : checks whether a socket of this name exists and, if so, if it is connected.
  198. ;;; Value : T, if the check succeeds; NIL otherwise.
  199. (let ((socket (getf (socket=sockets) socketname))
  200. (astring (make-string 1))
  201. val)
  202. (if (getf socket 'port) t
  203. (cond ((and socket (numberp (getf socket 'socket)) T)
  204. (setq val (uread (getf socket 'socket) 1 astring))
  205. (cond ((eq val -2) ;; Socket is there, but nothing on the socket.
  206. T)
  207. ((eq val 1) ;; Socket is there and read one character.
  208. ;; Saving the character in the buffer-string of the socket.
  209. (setf (getf (getf (socket=sockets) socketname) 'buffer-string)
  210. (concatenate 'string
  211. (getf (getf (socket=sockets) socketname) 'buffer-string) (copy-seq (string (elt astring 0)))))
  212. T)))))))
  213. #+(or cmu (and allegro-version>= (version>= 5 0)))
  214. (defun socket-active? (socketname)
  215. ;;; Edited : 20-SEP-2000 14. Feb 2001
  216. ;;; Authors : Pollet serge
  217. ;;; Input : A socketname.
  218. ;;; Effect : Checks whether a socket of this name exists and, if so, if it is connected.
  219. ;;; Value : T, if the check succeeds; NIL otherwise.
  220. (let ((socket (socket=socketname.socket socketname)))
  221. (and socket
  222. (or (and (streamp socket) (open-stream-p socket)
  223. (not (and (listen socket)
  224. (eq (peek-char nil socket nil 'eof) 'eof)))) ;active sockets
  225. (not (equal socket 'unconnected)))))) ;passive sockets
  226. #+(or cmu (and allegro-version>= (version>= 5 0)))
  227. (defun socket-active? (socketname)
  228. ;;; Edited : 20-SEP-2000 14. Feb 2001
  229. ;;; Authors : Pollet serge
  230. ;;; Input : A socketname.
  231. ;;; Effect : Checks whether a socket of this name exists and, if so, if it is connected.
  232. ;;; Value : T, if the check succeeds; NIL otherwise.
  233. (let ((socket (socket=socketname.socket socketname)))
  234. (and socket
  235. (streamp socket)
  236. (open-stream-p socket)
  237. )))
  238. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  239. (defun socket-receives? (socketname)
  240. ;;; Edited : 10. Mar 1999
  241. ;;; Authors : serge
  242. ;;; Input : a socketname
  243. ;;; Effect : checks whether there is something coming over the socket.
  244. ;;; Value : T, if there is something; NIL otherwise.
  245. (let ((socketentry (getf (socket=sockets) socketname))
  246. (astring (make-string 1))
  247. val)
  248. (cond ((and socketentry (numberp (getf socketentry 'socket)) T)
  249. (setq val (uread (getf socketentry 'socket) 1 astring))
  250. (cond ((eq val -2) ;; Socket is there, but nothing on the socket.
  251. nil)
  252. ((eq val 1) ;; Socket is there and read one character.
  253. ;;; Saving the character in the buffer-string of the socket.
  254. (setf (getf (getf (socket=sockets) socketname) 'buffer-string)
  255. (concatenate 'string
  256. (getf (getf (socket=sockets) socketname) 'buffer-string) (copy-seq (string (elt astring 0)))))
  257. T))))))
  258. #+(or cmu (and allegro-version>= (version>= 5 0)))
  259. (defun socket-receives? (socketname)
  260. ;;; Edited : 20-SEP-2000 14. Feb 2001
  261. ;;; Authors : Pollet serge
  262. ;;; Input : A socketname.
  263. ;;; Effect : Checks whether there is something coming over the socket.
  264. ;;; Value : T, if there is something; NIL otherwise.
  265. (let ((socket (socket=socketname.socket socketname)))
  266. (and socket (socket-active? socketname)
  267. #+(and allegro-version>= (version>= 5 0)) (stream::stream-listen socket)
  268. #+CMU (common-lisp:listen socket)
  269. )))
  270. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  271. (defun socket-fd (socketname)
  272. ;;; Edited : 12. Mar 1999
  273. ;;; Authors : serge
  274. ;;; Input : a socketname
  275. ;;; Effect : /
  276. ;;; Value :the file descriptor of this socket
  277. (getf (getf (socket=sockets) socketname) 'socket)
  278. )
  279. #+(or cmu (and allegro-version>= (version>= 5 0)))
  280. (defun socket-fd (socketname)
  281. ;;; Edited : 20-SEP-2000 14. Feb 2001
  282. ;;; Authors : Pollet serge
  283. ;;; Input : A socketname.
  284. ;;; Effect : -
  285. ;;; Value : The file descriptor of this socket.
  286. (let ((socket (socket=socketname.socket socketname)))
  287. (when (socket-active? socketname)
  288. #+(and allegro-version>= (version>= 5 0)) (socket::socket-os-fd socket)
  289. #+cmu (SYSTEM:FD-STREAM-FD socket)
  290. )))
  291. ;; ---------------------------------------------------------------------------
  292. ;; Section 3 : Connecting/Closing sockets.
  293. ;; ---------------------------------------------------------------------------
  294. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  295. (defun socket-connect (host port socketname)
  296. ;;; Edited : 17.03.1997 01.12.1998
  297. ;;; Authors : hess serge
  298. ;;; Input : A host and a portnumber to connect to.
  299. ;;; Effect : Connects to the specified socket.
  300. ;;; Value : /
  301. (let (socket)
  302. (cond ((and (setq socket (getf (socket=sockets) socketname))
  303. (eq (getf socket 'socket) 'unconnected))
  304. (setf (getf (getf socket*sockets socketname) 'socket) (uconnect host port)))
  305. ((null socket)
  306. (format t "Socket name ~A not defined" socketname))
  307. (t (format t "Socket ~A already connected." socketname)))))
  308. #+(or cmu (and allegro-version>= (version>= 5 0)))
  309. (defun socket-connect (host port socketname)
  310. ;;; Edited : 20-SEP-2000 14. Feb 2001
  311. ;;; Authors : Pollet serge
  312. ;;; Input : A host and a portnumber to connect to.
  313. ;;; Effect : Connects to the specified socket.
  314. ;;; Value : T for success, NIL for failure.
  315. (let (socket)
  316. (cond ((and (setq socket (socket=socketname.socket socketname))
  317. (equal socket 'unconnected))
  318. (setf (gethash socketname socket*sockets)
  319. (list 'socket
  320. #+(and allegro-version>= (version>= 5 0))
  321. (socket::make-socket :remote-host host
  322. :remote-port port
  323. :type :stream
  324. :address-family :internet
  325. :connect :active)
  326. #+CMU
  327. (system:make-fd-stream (connect-to-inet-socket host port)
  328. :input t :output t)
  329. 'buffer-string ""))
  330. T)
  331. ((null socket)
  332. (format t "Socket name ~A not defined" socketname)
  333. nil)
  334. (t (format t "Socket ~A already connected." socketname)
  335. nil))))
  336. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  337. (defun socket-close (socketname)
  338. ;;; Edited : 17.03.1997 01.12.1998
  339. ;;; Authors : hess serge
  340. ;;; Input : /
  341. ;;; Effect : Closes the connection to the socket.
  342. ;;; Value : /
  343. (let ((socket (getf (socket=sockets) socketname)))
  344. (cond ((and socket (not (equal (getf socket 'socket) 'unconnected)))
  345. (when (> (uclose (getf socket 'socket)) -1)
  346. (setf (getf socket 'port) nil)
  347. (setf (getf socket 'socket) 'unconnected))
  348. (setf (getf socket 'buffer-string) "")
  349. )
  350. ((null socket) (format t "Unknown socket ~A given to socket-close!" socketname) "")
  351. (t (format t "Socket ~A is not connected in socket-close!" socketname) ""))))
  352. #+(or cmu (and allegro-version>= (version>= 5 0)))
  353. (defun socket-close (socketname)
  354. ;;; Edited : 20-SEP-2000 14. Feb 2001
  355. ;;; Authors : Pollet serge
  356. ;;; Input : A socket name.
  357. ;;; Effect : Closes the connection to the socket. If error-p is not NIL an error is
  358. ;;; signaled on failure.
  359. ;;; Value : T for success, NIL for failure.
  360. (let ((socket (socket=socketname.socket socketname)))
  361. (cond ((and socket (not (equal socket 'unconnected)))
  362. #+(and allegro-version>= (version>= 5 0)) (socket::close socket)
  363. #+CMU (close-socket (SYSTEM:FD-STREAM-FD socket))
  364. (setf (getf (gethash socketname (socket=sockets)) 'socket) 'unconnected)
  365. T)
  366. ((null socket)
  367. (format t "Unknown socket ~A given to socket-close!" socketname)
  368. nil
  369. )
  370. (t (format t "Socket ~A is not connected in socket-close!" socketname)
  371. nil
  372. ))))
  373. ;; ---------------------------------------------------------------------------
  374. ;; Section 4 : Read from/Write to sockets.
  375. ;; ---------------------------------------------------------------------------
  376. (defvar socket*end-of-string
  377. ;;; Edited : 09.12.1998
  378. ;;; Authors : serge
  379. ;;; Descri. : the character indicating the end of a string to be read from a socket.
  380. (code-char 128))
  381. (proclaim '(type character socket*end-of-string))
  382. (defmacro socket=end-of-string ()
  383. ;;; Edited : 09.12.1998
  384. ;;; Authors : serge
  385. ;;; Input : /
  386. ;;; Effect : /
  387. ;;; Value : the actual value of `socket*end-of-string
  388. `socket*end-of-string)
  389. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  390. (defun socket=readloop (socket &optional wait? (eos (socket=end-of-string)))
  391. ;;; Edited : 17.03.1997 01.12.1998 09.12.1998 12. Jan 1999 19. Feb 1999
  392. ;;; Authors : hess serge serge serge serge
  393. ;;; Input : a socket description, which is a property list ('SOCKET socket 'BUFFER-STRING string)
  394. ;;; Effect : /
  395. ;;; Value : A string read from the socket, if there is some terminating with (socket=end-of-string).
  396. ;;; NIL if there is nothing on the socket. If there is something on the socket, but the end-of-string
  397. ;;; character (socket=end-of-string) has not been read, waits for this character.
  398. (let ((val 1)
  399. (astring (make-string 1 :initial-element (code-char 32)))
  400. (local-stream (make-string-output-stream))
  401. (overall-string (getf socket 'buffer-string))
  402. (the-socket (getf socket 'socket))
  403. (result nil)
  404. tmp)
  405. ;; Writing the actual content of the socket-buffer into the local-stream
  406. (write-string (socket=socketname.buffer-string socketname) local-stream)
  407. (do ()
  408. ;;; Read from socket one character, until we got the end-of-string character or an error.
  409. ((or (eq eos (elt astring 0)) (< val 1)))
  410. (when (eq 1 (setq val (if wait? (ureadwait the-socket 1 astring)
  411. (uread the-socket 1 astring))))
  412. ;;; Store the recently read character in the overall string.
  413. (unless (eq eos (elt astring 0))
  414. (when (and tmp (eq tmp #\\)
  415. (not (member (elt astring 0) (list #\\ #\"))))
  416. (write-char #\\ local-stream))
  417. (write-char (elt astring 0) local-stream)
  418. (setq tmp (elt astring 0))))
  419. ;; (setq overall-string (concatenate 'string overall-string (copy-seq (string (elt astring 0))))))
  420. )
  421. (cond ((< val 1) ;;; if we got an error on the socket, save the string read so far in the socket buffer and return NIL.
  422. (setq result nil)
  423. (setf (getf socket 'buffer-string) (get-output-stream-string local-stream))
  424. (cond ;; ((eq val -2) ;; (format t "No more symbols on the socket.~%"))
  425. ((eq val -1) (format t "General read error on the socket.~%"))
  426. ((eq val 0) (format t "Got an EOF on the socket. The other side might have closed/lost the socket.~%")))
  427. )
  428. (T ;;; otherwise return the actual string and delete the socket buffer.
  429. (setf (getf socket 'buffer-string) "")
  430. (setq result (get-output-stream-string local-stream))))
  431. result))
  432. #+(or cmu (and allegro-version>= (version>= 5 0)))
  433. (defun socket=readloop (socketname &optional wait? (eos (socket=end-of-string)))
  434. ;;; Edited : 20-SEP-2000 14. Feb 2001
  435. ;;; Authors : Pollet serge
  436. ;;; Input : A socket.
  437. ;;; Effect : -
  438. ;;; Value : A string read from the socket, if there is some terminating with (socket=end-of-string).
  439. ;;; NIL if there is nothing on the socket. If there is something on the socket, but the end-of-string
  440. ;;; character (socket=end-of-string) has not been read, waits for this character.
  441. (let ((astring nil)
  442. (socket (socket=socketname.socket socketname))
  443. (local-stream (make-string-output-stream))
  444. (result nil)
  445. (tmp nil))
  446. ;; Writing the actual content of the socket-buffer into the local-stream
  447. (write-string (socket=socketname.buffer-string socketname) local-stream)
  448. (do ()
  449. ;;; Read from socket one character, until we got the end-of-string character or an error.
  450. ((or (eq eos astring)
  451. (eq astring :eof)
  452. )
  453. )
  454. (when (socket-receives? socketname)
  455. (setf astring
  456. #+ALLEGRO (if wait? (stream-read-char socket) (read-char-no-hang socket))
  457. #+CMU18 (if wait? (common-lisp:read-char socket) (common-lisp:read-char-no-hang socket))
  458. )
  459. ;; (format t "Read on socket ~A the character: ~S~%" socketname astring)
  460. ;; Store the recently read character in the overall string.
  461. (unless (or (eq eos astring) (eq astring :eof))
  462. (when (and tmp (eq tmp #\\)
  463. (not (member astring (list #\\ #\"))))
  464. (write-char #\\ local-stream))
  465. (write-char astring local-stream)
  466. (setq tmp astring)))
  467. )
  468. (cond ((and astring (eq astring eos))
  469. (setq result (get-output-stream-string local-stream))
  470. (setf (getf (gethash socketname (socket=sockets)) 'buffer-string) ""))
  471. ((socket-active? socketname)
  472. (setf (getf (gethash socketname (socket=sockets)) 'buffer-string)
  473. (get-output-stream-string local-stream)))
  474. (t (format t "General read error on the socket. The other side might have loast/closed the connection.~%")))
  475. result))
  476. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  477. (defun socket-read (socketname &optional (wait? nil) (eos (socket=end-of-string)))
  478. ;;; Edited : 24.03.1997 01.12.1998 19. Feb 1999
  479. ;;; Authors : hess serge serge
  480. ;;; Input : /
  481. ;;; Effect : Write handshake signal to socket.
  482. ;;; Value : The string read from the socket.
  483. (let* ((socket (getf (socket=sockets) socketname)))
  484. (cond ((and socket (not (equal (getf socket 'socket) 'unconnected)))
  485. (socket=readloop socket wait? eos))
  486. ((null socket) (format t "Unknown socket ~A given to read from!" socketname) "")
  487. (t (format t "Socket ~A is not connected in read-socket!" socketname) ""))))
  488. #+(or cmu (and allegro-version>= (version>= 5 0)))
  489. (defun socket-read (&optional (socketname :inout) (wait? nil) (eos (socket=end-of-string)))
  490. ;;; Edited : 20-SEP-2000 14. Feb 2001
  491. ;;; Authors : Pollet serge
  492. ;;; Input : Socketname, wait-switch, signal-error-switch.
  493. ;;; Effect : Write handshake signal to socket. If error-p is not NIL an error is
  494. ;;; signaled on failure.
  495. ;;; Value : The string read from the socket on success, the empty string on failure.
  496. (let* ((socket (socket=socketname.socket socketname)))
  497. (cond ((and socket (not (equal socket 'unconnected)))
  498. (socket=readloop socketname wait? eos))
  499. ((null socket)
  500. (format t "Unknown socket ~A given to read from!" socketname)
  501. "")
  502. (t
  503. (format t "Socket ~A is not connected in read-socket!" socketname)
  504. ""))))
  505. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  506. (defun socket-write (string socketname &optional (eos (socket=end-of-string)))
  507. ;;; Edited : 24.03.1997 01.12.1998
  508. ;;; Authors : hess serge
  509. ;;; Input : A string and the name of a socket.
  510. ;;; Effect : Wait for ready signal, then write string to socket.
  511. ;;; Value : undef.
  512. (let ((socket (getf (socket=sockets) socketname)))
  513. (cond ((and socket (not (equal (getf socket 'socket) 'unconnected)))
  514. (uwrite (getf socket 'socket) (concatenate 'string string (string eos))))
  515. ((null socket) (format t "Unknown socket ~A given to write to!" socketname) nil)
  516. (t (format t "Socket ~A is not connected in write-socket!" socketname) nil))))
  517. #+(or cmu (and allegro-version>= (version>= 5 0)))
  518. (defun socket-write (string &optional (socketname :inout)
  519. (eos (string socket*end-of-string))
  520. )
  521. ;;; Edited : 20-SEP-2000 14. Feb 2001
  522. ;;; Authors : Pollet serge
  523. ;;; Input : A string and the name of a socket.
  524. ;;; Effect : Wait for ready signal, then write string to socket..
  525. ;;; Value : T for success, NIL for failure.
  526. (let ((socket (socket=socketname.socket socketname)))
  527. (cond ((and socket (not (equal socket 'unconnected)))
  528. (write-string (concatenate 'string string (string eos)) socket)
  529. (force-output socket)
  530. T)
  531. ((null socket)
  532. (format t "Unknown socket ~A given to write to!" socketname)
  533. nil
  534. )
  535. (t
  536. (format t "Socket ~A is not connected in write-socket!" socketname)
  537. nil
  538. ))))
  539. ;; ---------------------------------------------------------------------------
  540. ;; Section 5 : Stuff for TCP-Server and HTTP
  541. ;; ---------------------------------------------------------------------------
  542. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  543. (defun socket-bind (port socketname)
  544. ;;; Edited : 04. Aug 2000 06. Sep 2000
  545. ;;; Authors : Pollet serge
  546. ;;; Input : A port and a the socketname of a defined socket.
  547. ;;; Effect : Establish a server at port PORT. If error-p in not NIL an error is
  548. ;;; signaled on failure.
  549. ;;; Value : T for success, NIL for failure.
  550. (let ((socket (getf (socket=sockets) socketname)))
  551. (if socket
  552. (if (eq (getf socket 'socket) 'unconnected)
  553. (let ((fd (ubind port)))
  554. (if (and (numberp fd) (plusp fd))
  555. (progn
  556. (setf (getf socket 'socket) fd)
  557. (setf (getf socket 'port) port)
  558. t)
  559. (progn (format t "Problems to bind port ~A to socket ~A." port socketname)
  560. nil)))
  561. (progn (format t "Socket ~A already connected." socketname)
  562. nil))
  563. (progn (format t "Socket name ~A not defined" socketname)
  564. nil))))
  565. #+(or cmu (and allegro-version>= (version>= 5 0)))
  566. (defun socket-bind (port socketname)
  567. ;;; Edited : 04-AUG-2000 14. Feb 2001
  568. ;;; Authors : Pollet serge
  569. ;;; Input : A port and a the socketname of a defined socket.
  570. ;;; Effect : Establish a server at port PORT. If error-p in not NIL an error is
  571. ;;; signaled on failure.
  572. ;;; Value : T for success, NIL for failure.
  573. (let ((socket (socket=socketname.socket socketname))
  574. (newsocket nil))
  575. (if socket
  576. (if (eq socket 'unconnected)
  577. #+(and allegro-version>= (version>= 5 0))
  578. (handler-case
  579. (progn (setf (getf (gethash socketname (socket=sockets)) 'socket)
  580. (socket::make-socket :connect :passive :local-port port))
  581. t)
  582. (excl::socket-error (x)
  583. (format t "Error ~%~A~% while binding socket ~A on port ~D!~%" x socketname port)
  584. nil))
  585. #+CMU
  586. (handler-case
  587. (progn (setf (getf (gethash socketname (socket=sockets)) 'socket)
  588. (system:make-fd-stream (create-inet-listener port)
  589. :input t :output t))
  590. T)
  591. (error (x)
  592. (format t "Error ~%~A~% while binding socket ~A on port ~D!~%" x socketname port)
  593. nil))
  594. (progn (format t "Socket ~A already connected." socketname)
  595. nil))
  596. (progn
  597. (format t "Socket name ~A not defined" socketname)
  598. nil))))
  599. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  600. (defun socket-accept (serversocket connectsocket)
  601. ;;; Edited : 04. Aug 2000 06. Sep 2000
  602. ;;; Authors : Pollet serge
  603. ;;; Input : Two socketnames
  604. ;;; Effect : Waits for a connection on SERVERSOCKET. If this
  605. ;;; happens, CONNECTSOCKET will be connected to client.
  606. ;;; Value : T for success, NIL for failure.
  607. (let ((ssock (getf (socket=sockets) serversocket))
  608. (csock (getf (socket=sockets) connectsocket)))
  609. (if (and csock ssock)
  610. (if (eq (getf csock 'socket) 'unconnected)
  611. (let ((fd (uaccept (getf ssock 'socket))))
  612. (if (and (numberp fd) (plusp fd))
  613. (progn (setf (getf csock 'socket) fd)
  614. t)
  615. (progn (format t "Problems to accept ~A." serversocket)
  616. nil)))
  617. (progn (format t "Socket ~A already connected." connectsocket)
  618. nil))
  619. (progn (format t "Socket name ~A or ~A not defined" serversocket connectsocket)
  620. nil))))
  621. #+(or cmu (and allegro-version>= (version>= 5 0)))
  622. (defun socket-accept (serversocket connectsocket)
  623. ;;; Edited : 04-AUG-2000 14. Feb 2001
  624. ;;; Authors : Pollet serge
  625. ;;; Input : Two socketnames.
  626. ;;; Effect : Waits for a connection on SERVERSOCKET. If this happens, CONNECTSOCKET will be connected to client.
  627. ;;; If error-p is not NIL an error is signalled on failure.
  628. ;;; Value : T for success, NIL for failure.
  629. (let ((ssock (socket=socketname.socket serversocket))
  630. (csock (socket=socketname.socket connectsocket)))
  631. (cond ((not (and csock ssock))
  632. (format t "Socket name ~A or ~A not defined" serversocket connectsocket)
  633. nil)
  634. ((not (eq csock 'unconnected))
  635. (format t "Socket ~A already connected." connectsocket)
  636. nil)
  637. ((eq ssock 'unconnected)
  638. (format t "Socket ~A not connected." connectsocket)
  639. nil)
  640. ((streamp csock)
  641. (format t "Socket ~A is not a passive socket." connectsocket)
  642. nil)
  643. (T
  644. (progn
  645. (setf (getf (gethash connectsocket (socket=sockets)) 'socket)
  646. #+(and allegro-version>= (version>= 5 0)) (socket::accept-connection ssock)
  647. #+CMU (system:make-fd-stream (accept-tcp-connection (system:fd-stream-fd ssock))
  648. :input t :output t)
  649. )
  650. T)))))
  651. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  652. (defun socket=readuntil (socket what &optional wait?)
  653. ;;; Edited : 06. Aug 2000 06. Sep 2000
  654. ;;; Authors : pollet serge
  655. ;;; Input : a socket description, which is a property list ('SOCKET socket 'BUFFER-STRING string)
  656. ;;; and a NUMBER or CHAR.
  657. ;;; Effect : Reads NUMBER chars from the socket or untill CHAR or (socket=end-of-string)
  658. ;;; Value : Returns a string containing the chars read.
  659. (let* ((val 1)
  660. (astring (make-string 1 :initial-element (code-char 32)))
  661. (local-stream (make-string-output-stream))
  662. (overall-string (getf socket 'buffer-string))
  663. (the-socket (getf socket 'socket))
  664. (result nil)
  665. (counter 0)
  666. (test (etypecase what
  667. (number #'(lambda (x)(declare (ignore x))(= counter what)))
  668. (character #'(lambda (x)(eq what (elt x 0))))
  669. (null #'(lambda (x)(declare (ignore x)) nil)))))
  670. (do ()
  671. ;;; Read from socket one character, until we got the end-of-string character or an error.
  672. ((or (funcall test astring)
  673. (eq (socket=end-of-string) (elt astring 0))
  674. (= val 0)
  675. ))
  676. (when (eq 1 (setq val (if wait? (ureadwait the-socket 1 astring)
  677. (uread the-socket 1 astring))))
  678. ;; Store the recently read character in the overall string.
  679. ;; (if not eq to socket=end-of-string
  680. (unless (or (eq (socket=end-of-string) (elt astring 0)))
  681. (setq counter (1+ counter))
  682. (write-char (elt astring 0) local-stream)))
  683. ;; (setq overall-string (concatenate 'string overall-string (copy-seq (string (elt astring 0))))))
  684. )
  685. (cond ((and (< val 1)(not (= val -2))) ;;; if we got an error on the socket, save the string read so far in the socket buffer and return NIL.
  686. (setq result nil)
  687. (setf (getf socket 'buffer-string)
  688. (concatenate 'string overall-string (get-output-stream-string local-stream)))
  689. (cond ;; ((eq val -2) ;; (format t "No more symbols on the socket.~%"))
  690. ((eq val -1) (format t "General read error on the socket.~%"))
  691. ((eq val 0) (format t "Got an EOF on the socket. The other side might have closed/lost the socket.~%")))
  692. )
  693. (T ;;; otherwise return the actual string and delete the socket buffer.
  694. (setf (getf socket 'buffer-string) "")
  695. (setq result
  696. (concatenate 'string overall-string (get-output-stream-string local-stream)))))
  697. result))
  698. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  699. (defun socket-read.line (socketname &optional (wait? nil))
  700. ;;; Edited : 06. Aug 2000 06. Sep 2000
  701. ;;; Authors : pollet serge
  702. ;;; Input : Socketname.
  703. ;;; Effect : Write handshake signal to socket. If error-p is not NIL an error is signaled on failure.
  704. ;;; Value : The string containing the line read from the socket.
  705. (let* ((socket (getf (socket=sockets) socketname)))
  706. (cond ((and socket (not (equal (getf socket 'socket) 'unconnected)))
  707. (socket=readuntil socket #\newline wait?))
  708. ((null socket)
  709. (format t "Unknown socket ~A given to read from!" socketname)
  710. "")
  711. (t (format t "Socket ~A is not connected in read-socket!" socketname)
  712. ""))))
  713. #+(or cmu (and allegro-version>= (version>= 5 0)))
  714. (defun socket-read.line (socketname &optional (wait? nil))
  715. ;;; Edited : 06-AUG-2000 14. Feb 2001
  716. ;;; Authors : Pollet serge
  717. ;;; Input : Socketname.
  718. ;;; Effect : Write handshake signal to socket. If error-p is not NIL an error is signaled on failure.
  719. ;;; Value : The string containing the line read from the socket.
  720. (let* ((socket (socket=socketname.socket socketname)))
  721. (cond ((and socket (not (equal socket 'unconnected)))
  722. (read-line socket nil nil))
  723. ((null socket)
  724. (format t "Unknown socket ~A given to read from!" socketname)
  725. "")
  726. (t (format t "Socket ~A is not connected in read-socket!" socketname)
  727. ""))))
  728. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  729. (defun socket-read.content (size socketname &optional (wait? nil) (error-p nil))
  730. ;;; Edited : 06. Aug 2000 06. Sep 2000
  731. ;;; Authors : pollet serge
  732. ;;; Input : Socketname and a number.
  733. ;;; Effect : Write handshake signal to socket. If error-p is not NIL an error is signaled on failure.
  734. ;;; Value : The string containing SIZE chars read from the socket.
  735. (let* ((socket (getf (socket=sockets) socketname)))
  736. (cond ((and socket (not (equal (getf socket 'socket) 'unconnected)))
  737. (socket=readuntil socket size wait?))
  738. ((null socket)
  739. (format t "Unknown socket ~A given to read from!" socketname)
  740. "")
  741. (t (format t "Socket ~A is not connected in read-socket!" socketname)
  742. ""))))
  743. #+(or cmu (and allegro-version>= (version>= 5 0)))
  744. (defun socket-read.content (size socketname &optional (wait? nil))
  745. ;;; Edited : 06-AUG-2000 14. Feb 2001
  746. ;;; Authors : Pollet serge
  747. ;;; Input : Socketname and a number.
  748. ;;; Effect : Write handshake signal to socket. If error-p is not NIL an error is signaled on failure.
  749. ;;; Value : The string containing SIZE chars read from the socket.
  750. ;; (warn "Socket-read.content with size ~A" size)
  751. (let* ((socket (socket=socketname.socket socketname)))
  752. (cond ((and socket (not (equal socket 'unconnected)))
  753. (let ((input (make-string size)))
  754. (read-sequence input socket)
  755. input))
  756. ((null socket)
  757. (format t "Unknown socket ~A given to read from!" socketname)
  758. "")
  759. (t (format t "Socket ~A is not connected in read-socket!" socketname)
  760. ""))))
  761. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  762. (defun socket-write.file (header pathname &optional (socketname :inout)
  763. (eos (string socket*end-of-string))
  764. (error-p nil))
  765. ;;; Edited : 24.03.1997 01.12.1998
  766. ;;; Authors : hess serge
  767. ;;; Input : A string and the name of a socket.
  768. ;;; Effect : Wait for ready signal, then write string to socket. If error-p is not NIL
  769. ;;; an error is signaled on failure.
  770. ;;; Value : T for success, NIL for failure.
  771. (let ((socket (getf (socket=sockets) socketname)))
  772. (cond ((and socket (not (equal (getf socket 'socket) 'unconnected)))
  773. (uwrite (getf socket 'socket) header)
  774. (uwritefile (getf socket 'socket) pathname)
  775. T)
  776. ((null socket)
  777. (when error-p
  778. (error "Unknown socket ~A given to write to!" socketname))
  779. (format t "Unknown socket ~A given to write to!" socketname)
  780. nil
  781. )
  782. (t
  783. (when error-p
  784. (error "Unknown socket ~A given to write to!" socketname))
  785. (format t "Socket ~A is not connected in write-socket!" socketname)
  786. nil
  787. ))))
  788. #+(and (not cmu) (not (and allegro-version>= (version>= 5 0))))
  789. (defun socket-get.peername (socketname)
  790. ;;; Edited : 29. Aug 2000 06. Sep 2000
  791. ;;; Authors : pollet serge
  792. ;;; Input : A Socketname
  793. ;;; Effect : Calls the foreign functions 'ugetpeername'.
  794. ;;; Value : A string with the IP number of the connected host.
  795. (let ((socket (getf (socket=sockets) socketname))
  796. val)
  797. (when (and socket (numberp (getf socket 'socket))
  798. (setq val (ugetpeername (getf socket 'socket))))
  799. (unless (= val -1)
  800. #+(or allegro-v5.0 allegro-v5.0.1)(excl:native-to-string val)
  801. #+(or allegro-v4.3 allegro-v4.3.1)(ff:char*-to-string val)
  802. ))))
  803. #+(or cmu (and allegro-version>= (version>= 5 0)))
  804. (defun socket-get.peername (socketname)
  805. ;;; Edited : 29-AUG-2000 14. Feb 2001
  806. ;;; Authors : Pollet serge
  807. ;;; Input : A Socketname
  808. ;;; Effect : -
  809. ;;; Value : A string with the IP number of the connected host.
  810. (let ((socket (socket=socketname.socket socketname)))
  811. (when socket
  812. #+(and allegro-version>= (version>= 5 0)) (socket::ipaddr-to-dotted (socket::remote-host socket))
  813. #+CMU (multiple-value-bind (ipaddr port) (get-peer-host-and-port (system:fd-stream-fd socket))
  814. ipaddr)
  815. )))
  816. (provide "socket-interface")