File: ecl.lisp

package info (click to toggle)
acl2 7.2dfsg-3
  • links: PTS
  • area: main
  • in suites: stretch
  • size: 198,968 kB
  • ctags: 182,300
  • sloc: lisp: 2,415,261; ansic: 5,675; perl: 5,577; xml: 3,576; sh: 3,255; cpp: 2,835; makefile: 2,440; ruby: 2,402; python: 778; ml: 763; yacc: 709; csh: 355; php: 171; lex: 162; tcl: 44; java: 24; asm: 23; haskell: 17
file content (154 lines) | stat: -rw-r--r-- 5,162 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
;;;; -*- Mode: Lisp -*-
;;;; $Id$
;;;; $URL$

;;;; Foreign functions defined by ECL's DFFI, used for #+ecl-bytecmp only.
;;;; See LICENSE for licensing information.

(in-package :usocket)

#+(and ecl-bytecmp windows)
(eval-when (:load-toplevel :execute)
  (ffi:load-foreign-library "ws2_32.dll" :module "ws2_32"))

#+(and ecl-bytecmp windows)
(progn
  (ffi:def-function ("gethostname" c-gethostname)
    ((name (* :unsigned-char))
     (len :int))
    :returning :int
    :module "ws2_32")

  (defun get-host-name ()
    "Returns the hostname"
    (ffi:with-foreign-object (name '(:array :unsigned-char 256))
      (when (zerop (c-gethostname (ffi:char-array-to-pointer name) 256))
        (ffi:convert-from-foreign-string name))))

  (ffi:def-foreign-type ws-socket :unsigned-int)
  (ffi:def-foreign-type ws-dword :unsigned-long)
  (ffi:def-foreign-type ws-event :unsigned-int)

  (ffi:def-struct wsa-network-events
    (network-events :long)
    (error-code (:array :int 10)))

  (ffi:def-function ("WSACreateEvent" wsa-event-create)
    ()
    :returning ws-event
    :module "ws2_32")

  (ffi:def-function ("WSACloseEvent" c-wsa-event-close)
    ((event-object ws-event))
    :returning :int
    :module "ws2_32")

  (defun wsa-event-close (ws-event)
    (not (zerop (c-wsa-event-close ws-event))))

  (ffi:def-function ("WSAEnumNetworkEvents" wsa-enum-network-events)
    ((socket ws-socket)
     (event-object ws-event)
     (network-events (* wsa-network-events)))
    :returning :int
    :module "ws2_32")

  (ffi:def-function ("WSAEventSelect" wsa-event-select)
    ((socket ws-socket)
     (event-object ws-event)
     (network-events :long))
    :returning :int
    :module "ws2_32")

  (ffi:def-function ("WSAWaitForMultipleEvents" c-wsa-wait-for-multiple-events)
    ((number-of-events ws-dword)
     (events (* ws-event))
     (wait-all-p :int)
     (timeout ws-dword)
     (alertable-p :int))
    :returning ws-dword
    :module "ws2_32")

  (defun wsa-wait-for-multiple-events (number-of-events events wait-all-p timeout alertable-p)
    (c-wsa-wait-for-multiple-events number-of-events
                                    events
                                    (if wait-all-p -1 0)
                                    timeout
                                    (if alertable-p -1 0)))

  (ffi:def-function ("ioctlsocket" wsa-ioctlsocket)
    ((socket ws-socket)
     (cmd :long)
     (argp (* :unsigned-long)))
    :returning :int
    :module "ws2_32")

  (ffi:def-function ("WSAGetLastError" wsa-get-last-error)
    ()
    :returning :int
    :module "ws2_32")

  (defun maybe-wsa-error (rv &optional socket)
    (unless (zerop rv)
      (raise-usock-err (wsa-get-last-error) socket)))

  (defun bytes-available-for-read (socket)
    (ffi:with-foreign-object (int-ptr :unsigned-long)
      (maybe-wsa-error (wsa-ioctlsocket (socket-handle socket) fionread int-ptr)
                       socket)
      (let ((int (ffi:deref-pointer int-ptr :unsigned-long)))
        (prog1 int
          (when (plusp int)
            (setf (state socket) :read))))))

  (defun map-network-events (func network-events)
    (let ((event-map (ffi:get-slot-value network-events 'wsa-network-events 'network-events))
          (error-array (ffi:get-slot-pointer network-events 'wsa-network-events 'error-code)))
      (unless (zerop event-map)
        (dotimes (i fd-max-events)
          (unless (zerop (ldb (byte 1 i) event-map))
            (funcall func (ffi:deref-array error-array '(:array :int 10) i)))))))

  (defun update-ready-and-state-slots (sockets)
    (dolist (socket sockets)
      (if (%ready-p socket)
          (progn
            (setf (state socket) :READ))
        (ffi:with-foreign-object (network-events 'wsa-network-events)
          (let ((rv (wsa-enum-network-events (socket-handle socket) 0 network-events)))
            (if (zerop rv)
                (map-network-events
                 #'(lambda (err-code)
                     (if (zerop err-code)
                         (progn
                           (setf (state socket) :READ)
                           (when (stream-server-usocket-p socket)
                             (setf (%ready-p socket) t)))
                       (raise-usock-err err-code socket)))
                 network-events)
              (maybe-wsa-error rv socket)))))))

  (defun os-wait-list-%wait (wait-list)
    (ffi:deref-pointer (wait-list-%wait wait-list) 'ws-event))

  (defun (setf os-wait-list-%wait) (value wait-list)
    (setf (ffi:deref-pointer (wait-list-%wait wait-list) 'ws-event) value))

  (defun free-wait-list (wl)
    (when (wait-list-p wl)
      (unless (null (wait-list-%wait wl))
        (wsa-event-close (os-wait-list-%wait wl))
        (ffi:free-foreign-object (wait-list-%wait wl))
        (setf (wait-list-%wait wl) nil))))

  (defun %setup-wait-list (wait-list)
    (setf (wait-list-%wait wait-list)
          (ffi:allocate-foreign-object 'ws-event))
    (setf (os-wait-list-%wait wait-list)
          (wsa-event-create))
    (ext:set-finalizer wait-list #'free-wait-list))

  (defun os-socket-handle (usocket)
    (socket-handle usocket))

) ; #+(and ecl-bytecmp windows)