2 % (c) The GRASP/AQUA Project, Glasgow University, 1995
4 % Last Modified: Fri Jul 21 15:14:43 1995
5 % Darren J Moffat <moffatd@dcs.gla.ac.uk>
6 \section[Socket]{Haskell 1.3 Socket bindings}
18 socket, -- :: Family -> SocketType -> Int -> IO Socket
19 connect, -- :: Socket -> SockAddr -> IO ()
20 bindSocket, -- :: Socket -> SockAddr -> IO ()
21 listen, -- :: Socket -> Int -> IO ()
22 accept, -- :: Socket -> IO (Socket, SockAddr)
23 getPeerName, -- :: Socket -> IO SockAddr
24 getSocketName, -- :: Socket -> IO SockAddr
26 socketPort, -- :: Socket -> IO Int
28 writeSocket, -- :: Socket -> String -> IO Int
29 readSocket, -- :: Socket -> Int -> IO (String, Int)
30 readSocketAll, -- :: Socket -> IO String
32 socketToHandle, -- :: Socket -> IO Handle
34 -- Alternative read/write interface not yet implemented.
35 -- sendto -- :: Socket -> String -> SockAddr -> IO Int
36 -- recvfrm -- :: Socket -> Int -> SockAddr -> IO (String, Int)
37 -- sendmsg -- :: Socket -> Message -> MsgFlags -> IO Int
38 -- recvmsg -- :: Socket -> MsgFlags -> IO Message
40 shutdown, -- :: Socket -> Int -> IO ()
41 sClose, -- :: Socket -> IO ()
43 inet_addr, -- :: String -> HostAddress
44 inet_ntoa, -- :: HostAddress -> String
46 sIsConnected, -- :: Socket -> IO Bool
47 sIsBound, -- :: Socket -> IO Bool
48 sIsListening, -- :: Socket -> IO Bool
49 sIsReadable, -- :: Socket -> IO Bool
50 sIsWritable, -- :: Socket -> IO Bool
62 -- The following are exported ONLY for use in the BSD module and
63 -- should not be used else where.
65 packFamily, unpackFamily,
67 packSockAddr, unpackSockAddr
75 import PreludePrimIO ( newEmptyMVar, putMVar, _MVar )
80 %************************************************************************
82 \subsection[Socket-SocketTypes]{Socket Types}
84 %************************************************************************
87 There are a few possible ways to do this. The first is convert the
88 structs used in the C library into an equivalent Haskell type. An
89 other possible implementation is to keep all the internals in the C
90 code and use an Int\# and a status flag. The second method is used here
91 since a lot of the C structures are not required to be manipulated.
92 Originally the status was non mutable so we had to return a new socket
93 each time we changed the status. This version now uses mutable
94 variables to avoid the need to do this. The result is a cleaner
95 interface and better security since the application programmer now
96 can't circumvent the status information to perform invalid operations
102 -- Returned Status Function called
103 NotConnected -- socket
104 | Bound -- bindSocket
105 | Listening -- listen
106 | Connected -- connect/accept
107 | Error String -- Any
110 data Socket = MkSocket
111 Int -- File Descriptor Part
114 Int -- Protocol Number
115 (MutableVar _RealWorld SocketStatus) -- Status Flag
120 In C bind takes either a $struct sockaddr_in$ or a $struct
121 sockaddr_un$ but these are always type cast to $struct sockaddr$. We
122 attempt to emulate this and provide better type checking. Note that
123 the socket family fields are redundant since this is caputured in the
124 constructor names, it has thus be left out of the Haskell $SockAddr$
129 type HostAddress = _Word
131 data SockAddr = -- C Names
132 SockAddrUnix -- struct sockaddr_un
135 | SockAddrInet -- struct sockaddr_in
137 HostAddress -- sin_addr
145 %************************************************************************
147 \subsection[Socket-Connections]{Connection Functions}
149 %************************************************************************
152 In the following connection and binding primitives. The names of the
153 equivalent C functions have been preserved where possible. It should
154 be noted that some of these names used in the C library, bind in
155 particular, have a different meaning to many Haskell programmers and
156 have thus been renamed by appending the prefix Socket.
159 Create an unconnected socket of the given family, type and protocol.
160 The most common invocation of $socket$ is the following:
163 socket AF_INET Stream 6 >>= \ my_socket ->
168 socket :: Family -> -- Family Name (usually AF_INET)
169 SocketType -> -- Socket Type (usually Stream)
170 Int -> -- Protocol Number (getProtocolByName to find value)
171 IO Socket -- Unconnected Socket
173 socket family stype protocol =
174 _ccall_ socket (packFamily family) (packSocketType stype) protocol
177 getCErrorCode `thenPrimIO` \ errno ->
180 fail "socket: Permission Denied"
182 fail "socket: No more descriptiors available"
184 fail "socket: System file table is full"
186 fail "socket: Insufficient Buffer space to create socket"
188 fail ("socket: Protocol " ++ show protocol ++
189 " not supported for Family " ++ show family)
191 fail ("socket: Protocol " ++ show protocol ++
192 " wrong type for socket")
194 fail ("socket: " ++ (errorCodeToStr errno))
197 newVar NotConnected `thenPrimIO` \ status ->
198 return (MkSocket s family stype protocol status)
201 Given a port number this {\em binds} the socket to that port. This
202 means that the programmer is only interested in data being sent to
203 that port number. The $Family$ passed to $bindSocket$ must
204 be the same as that passed to $socket$. If the special port
205 number $aNY_PORT$ is passed then the system assigns the next
208 Port numbers for standard unix services can be found by calling
209 $getServiceEntry$. These are traditionally port numbers below
210 1000; although there are afew, namely NFS and IRC, which used higher
213 The port number allocated to a socket bound by using $aNY_PORT$ can be
214 found by calling $port$
217 bindSocket :: Socket -> -- Unconnected Socket
218 SockAddr -> -- Address to Bind to
221 bindSocket (MkSocket s family stype protocol status) addr =
222 readVar status `thenST` \ currentStatus ->
223 if currentStatus /= NotConnected then
224 fail ("bindSocket: can't peform bind on socket in status " ++
227 packSockAddr addr `thenPrimIO` \ addr' ->
228 let (_,sz) = boundsOfByteArray addr' in
229 _casm_ ``%r = bind(%0, (struct sockaddr*)%1, %2);''
230 s addr' sz `thenPrimIO` \ result ->
232 getCErrorCode `thenPrimIO` \ errno ->
235 fail "bindSocket: The requested address is protected"
237 fail "bindSocket: Address in use by another process"
239 fail "bindSocket: Address not available"
241 fail "bindSocket: invalid descriptor"
243 fail "bindSocket: name parameter not in vaild user address space"
245 fail "bindSocket: namelen invalid size for given family"
247 fail "bindSocket: attempt to bind a non socket descriptor"
249 fail ("bindSocket: " ++ (errorCodeToStr errno))
252 writeVar status (Bound) `seqPrimIO`
258 Make a connection to an already opened socket on a given machine and port.
259 assumes that we have already called createSocket, othewise it will fail.
261 This is the dual to $bindSocket$. The {\em server} process will
262 usually bind to a port number, the {\em client} will then connect to
263 the same port number. Port numbers of user applications are normally
264 agreed in advance, otherwise we must rely on some hacky mechanism for telling
265 the {\em otherside} what port number we have been allocated.
268 connect :: Socket -> -- Unconnected Socket
269 SockAddr -> -- Socket address stuff
272 connect (MkSocket s family stype protocol status) addr =
273 readVar status `thenST` \ currentStatus ->
274 if currentStatus /= NotConnected then
275 fail ("connect: can't peform connect on socket in status " ++
278 packSockAddr addr `thenPrimIO` \ addr' ->
279 let (_,sz) = boundsOfByteArray addr' in
280 _casm_ ``%r = connect(%0,(struct sockaddr*)%1, %2);''
281 s addr' sz `thenPrimIO` \ result ->
283 getCErrorCode `thenPrimIO` \ errno ->
286 fail "connect: address in use"
288 fail "connect: address not available on remote machine"
290 fail "connect: invalid socket address family"
292 fail ("connect: socket in non-blocking and previous " ++
293 "attempt to connect not yet complteted")
295 fail "connect: socket in not a vaild descriptor"
297 fail "connect: connection refused by peer"
299 fail "connect: address parameter outside process address space"
301 fail ("connect: socket is non-blocking and connection can " ++
302 "not be completed imediately")
304 fail "connect: connection interrupted before delivery signal"
306 fail ("connect: namlen not size of valid address for " ++
309 fail "connect: socket is already connected"
311 fail "connect: network unreachable"
313 fail "connect: file descriptor passed instead of socket"
315 fail "connect: timed out without establishing connection"
317 fail ("connect: " ++ (errorCodeToStr errno))
320 writeVar status (Connected) `seqPrimIO`
325 The programmer must call $listen$ to tell the system software
326 that they are now interested in receiving data on this port. This
327 must be called on the bound socket before any calls to read or write
330 The programmer also gives a number which indicates the length of the
331 incoming queue of unread messages for this socket. On most systems the
332 maximum queue length is around 5. To remove a message from the queue
333 for processing a call to $accept$ should be made.
336 listen :: Socket -> -- Connected & Bound Socket
337 Int -> -- Queue Length
340 listen (MkSocket s family stype protocol status) backlog =
341 readVar status `thenST` \ currentStatus ->
342 if currentStatus /= Bound then
343 fail ("listen: can't peform listen on socket in status " ++
346 _ccall_ listen s backlog `thenPrimIO` \ result ->
348 getCErrorCode `thenPrimIO` \ errno ->
351 fail "listen: socket file descriptor invalid"
353 fail "listen: file descriptor is not a socket"
355 fail "listen: not supported fro this type of socket"
357 fail ("listen: " ++ (errorCodeToStr errno))
360 writeVar status (Listening) `seqPrimIO`
364 A call to $accept$ only returns when data is available on the given
365 socket, unless the socket has been set to non-blocking. It will
366 return a new socket which should be used to read the incoming data and
367 should then be closed. Using the socket returned by $accept$ allows
368 incoming requests to be queued on the original socket.
372 accept :: Socket -> -- Queue Socket
373 IO (Socket, -- Readable Socket
374 SockAddr) -- Peer details
376 accept sock@(MkSocket s family stype protocol status) =
377 readVar status `thenST` \ currentStatus ->
378 sIsAcceptable sock >>= \ okay ->
380 fail ("accept: can't peform accept on socket in status " ++
383 allocSockAddr family `thenPrimIO` \ (ptr, sz) ->
384 _casm_ ``%r = accept(%0,(struct sockaddr*)%1, &%2);''
385 s ptr sz `thenPrimIO` \ sock ->
387 getCErrorCode `thenPrimIO` \ errno ->
390 fail "accept: descriptor is invalid"
392 fail "accept: addr is not in writeable part of address space"
394 fail "accept: descriptor is not a socket"
396 fail ("accept: socket not of type" ++ show stype)
398 fail "accept: would block"
400 fail ("accept: " ++ (errorCodeToStr errno))
403 unpackSockAddr ptr `thenPrimIO` \ addr ->
404 newVar Connected `thenPrimIO` \ status ->
405 return ((MkSocket sock family stype protocol status), addr)
409 %************************************************************************
411 \subsection[Socket-DataPass]{Data Passing Primitives}
413 %************************************************************************
415 To allow Haskell to talk to C programs we need to beable to
416 communicate interms of byte streams. $writeSocket$ and
417 $readSocket$ should only be used for this purpose and not for
418 communication between Haskell programs. Haskell programs should use
419 the 1.3 IO hPutStr and associated machinery for communicating with
424 writeSocket :: Socket -> -- Connected Socket
425 String -> -- Data to send
426 IO Int -- Number of Bytes sent
428 writeSocket (MkSocket s family stype protocol status) xs =
429 readVar status `thenST` \ currentStatus ->
430 if not ((currentStatus /= Connected) || (currentStatus /= Listening)) then
431 fail ("writeSocket: can't peform write on socket in status " ++
434 _ccall_ write s xs (length xs) `thenPrimIO` \ nbytes ->
436 getCErrorCode `thenPrimIO` \ errno ->
439 fail "writeSocket: invalid file descriptor"
441 fail "writeSocket: disk quota exhausted"
443 fail "writeSocket: data area outside address space"
445 fail "writeSocket: max file size limit exeeded"
447 fail "writeSocket: interupt received before data written"
449 fail ("writeSocket: The stream is linked below a " ++
450 "multiplexor. The fd pointer was negative")
452 fail "writeSocket: no space left on device"
454 fail "writeSocket: hangup occured on stream"
456 fail "writeSocket: attempt to write to unopened pipe"
458 fail "writeSocket: to much data to write"
460 fail "writeSocket: would block"
462 fail "writeSocket: would block"
464 fail ("writeSocket: " ++ (errorCodeToStr errno))
469 readSocket :: Socket -> -- Connected Socket
470 Int -> -- Number of Bytes to Read
471 IO (String, Int) -- (Data Read, Number of Bytes)
473 readSocket (MkSocket s family stype protocol status) nbytes =
474 readVar status `thenST` \ currentStatus ->
475 if not ((currentStatus /= Connected) || (currentStatus /= Listening)) then
476 fail ("readSocket: can't perform read on socket in status " ++
479 -- newCharArray (0, nbytes) `thenPrimIO` \ ptr \ ->
480 _casm_ ``%r = (char*)malloc(1+sizeof(char)*%0);'' nbytes
481 `thenPrimIO` \ buffer ->
482 _ccall_ read s buffer nbytes `thenPrimIO` \ result ->
484 getCErrorCode `thenPrimIO` \ errno ->
487 fail "readSocket: no data to read (non-blocking)"
489 fail "readSocket: invalid file descriptor"
491 fail "readSocket: not a valid data message"
493 fail "readSocket: buffer outside allocated address space"
495 fail "readSocket: interupted by signal before data"
497 fail ("readSocket: The stream is linked below a " ++
498 "multiplexor. The file descriptor pointer was negative")
500 fail "readSocket: IO error"
502 fail "readSocket: descriptor is an NFS directory"
504 fail "readSocket: would block"
506 fail ("readSocket: " ++ (errorCodeToStr errno))
509 return (_unpackPS (_packCString buffer), result)
512 readSocketAll :: Socket -> IO String
516 readSocket s 4096 >>= \ (str, nbytes) ->
526 The port number the given socket is currently connected to can be
527 determined by calling $port$, is generally only useful when bind
528 was given $aNY_PORT$.
531 socketPort :: Socket -> -- Connected & Bound Socket
532 IO Int -- Port Number of Socket
533 socketPort sock@(MkSocket s AF_INET stype protocol status) =
534 getSocketName sock >>= \ (SockAddrInet port _) ->
536 socketPort (MkSocket s family stype protocol status) =
537 fail ("socketPort: not supported for Family " ++ show family)
540 Calling $getPeerName$ returns the address details of the machine,
541 other than the local one, which is connected to the socket. This is
542 used in programs such as FTP to determine where to send the returning
543 data. The corresponding call to get the details of the local machine
547 getPeerName :: Socket -> IO SockAddr
548 getPeerName (MkSocket s family stype protocol status) =
549 allocSockAddr family `thenPrimIO` \ (ptr,sz) ->
550 _casm_ ``%r = getpeername(%0,(struct sockaddr*)%1,&%2);''
551 s ptr sz `thenPrimIO` \ result ->
553 getCErrorCode `thenPrimIO` \ errno ->
554 fail ("getPeerName: " ++ (errorCodeToStr errno))
556 unpackSockAddr ptr `thenPrimIO` \ addr ->
559 getSocketName :: Socket -> IO SockAddr
560 getSocketName (MkSocket s family stype protocol status) =
561 allocSockAddr family `thenPrimIO` \ (ptr,sz) ->
562 _casm_ ``%r = getsockname(%0,(struct sockaddr*)%1, &%2);''
563 s ptr sz `thenPrimIO` \ result ->
565 getCErrorCode `thenPrimIO` \ errno ->
566 fail ("getSocketName: " ++ (errorCodeToStr errno))
568 unpackSockAddr ptr `thenPrimIO` \ addr ->
573 %************************************************************************
575 \subsection[Socket-Properties]{Socket Properties}
577 %************************************************************************
600 sOL_SOCKET = ``SOL_SOCKET''
602 setSocketOptions :: Socket ->
604 SocketOption -> -- Option Name
605 String -> -- Option Value
608 getSocketOptons :: Socket ->
610 SocketOption -> -- Option Name
611 IO String -- Option Value
615 A calling sequence table for the main functions is shown in the table below.
619 \begin{tabular}{|l|c|c|c|c|c|c|c|}
621 \textbf{A Call to} & socket & connect & bindSocket & listen & accept & read & write \\
623 \textbf{Precedes} & & & & & & & \\
625 socket & & & & & & & \\
627 connect & + & & & & & & \\
629 bindSocket & + & & & & & & \\
631 listen & & & + & & & & \\
633 accept & & & & + & & & \\
635 read & & + & & + & + & + & + \\
637 write & & + & & + & + & + & + \\
640 \caption{Sequence Table for Major functions of Socket}
645 %************************************************************************
647 \subsection[Socket-OSDefs]{OS Dependant Definitions}
649 %************************************************************************
652 The following Family and Socket Type declarations were manually derived
653 from /usr/include/sys/socket.h on the appropriate machines.
655 Maybe a configure script that could parse the socket.h file to produce
656 the following declaration is required to make it "portable" rather than
657 using the dreded \#ifdefs.
659 Presently only the following machine/os combinations are supported:
670 unpackFamily :: Int -> Family
671 packFamily :: Family -> Int
673 packSocketType :: SocketType -> Int
677 AF_UNSPEC -- unspecified
678 | AF_UNIX -- local to host (pipes, portals
679 | AF_INET -- internetwork: UDP, TCP, etc
680 | AF_IMPLINK -- arpanet imp addresses
681 | AF_PUP -- pup protocols: e.g. BSP
682 | AF_CHAOS -- mit CHAOS protocols
683 | AF_NS -- XEROX NS protocols
684 | AF_NBS -- nbs protocols
685 | AF_ECMA -- european computer manufacturers
686 | AF_DATAKIT -- datakit protocols
687 | AF_CCITT -- CCITT protocols, X.25 etc
689 | AF_DECnet -- DECnet
690 | AF_DLI -- Direct data link interface
692 | AF_HYLINK -- NSC Hyperchannel
693 | AF_APPLETALK -- Apple Talk
694 | AF_NIT -- Network Interface Tap
695 | AF_802 -- IEEE 80.2, also ISO 8802
696 | AF_OSI -- umberella of all families used by OSI
697 | AF_X25 -- CCITT X.25
699 | AF_GOSSIP -- US Government OSI
700 | AF_IPX -- Novell Internet Protocol
701 deriving (Eq, Ord, Ix, Text)
703 packFamily = index (AF_UNSPEC, AF_IPX)
704 unpackFamily family = (range (AF_UNSPEC, AF_IPX))!!family
711 AF_UNSPEC -- unspecified
712 | AF_UNIX -- local to host (pipes, portals)
713 | AF_INET -- internetwork: UDP, TCP, etc.
714 | AF_IMPLINK -- arpanet imp addresses
715 | AF_PUP -- pup protocols: e.g. BSP
716 | AF_CHAOS -- mit CHAOS protocols
717 | AF_NS -- XEROX NS protocols
718 | AF_ISO -- ISO protocols
719 | AF_ECMA -- european computer manufacturers
720 | AF_DATAKIT -- datakit protocols
721 | AF_CCITT -- CCITT protocols, X.25 etc
723 | AF_DECnet -- DECnet
724 | AF_DLI -- DEC Direct data link interface
726 | AF_HYLINK -- NSC Hyperchannel
727 | AF_APPLETALK -- Apple Talk
728 | AF_ROUTE -- Internal Routing Protocol
729 | AF_LINK -- Link layer interface
730 | Pseudo_AF_XTP -- eXpress Transfer Protocol (no AF)
731 | AF_NETMAN -- DNA Network Management
732 | AF_X25 -- X25 protocol
733 | AF_CTF -- Common Trace Facility
734 | AF_WAN -- Wide Area Network protocols
735 deriving (Eq, Ord, Ix, Text)
737 packFamily = index (AF_UNSPEC, AF_WAN)
738 unpackFamily family = (range (AF_UNSPEC, AF_WAN))!!family
749 deriving (Eq, Ord, Ix, Text)
751 packFamily = index (AF_UNSPEC, AF_IPX)
752 unpackFamily family = (range (AF_UNSPEC, AF_IPX))!!family
756 -- Alpha running OSF or a SPARC with SunOS, rather than Solaris.
758 #if __alpha__ || (sun && !__svr4__)
765 deriving (Eq, Ord, Ix, Text)
767 packSocketType stype = 1 + (index (Stream, SeqPacket) stype)
770 -- This is a Sun running Solaris rather than SunOS
780 deriving (Eq, Ord, Ix, Text)
782 packSocketType stype = 1 + (index (Datagram, SeqPacket) stype)
794 deriving (Eq, Ord, Ix, Text)
796 packSocketType stype = 1 + (index (Stream, Packet) stype)
801 %************************************************************************
803 \subsection[Socket-Util]{Utility Functions}
805 %************************************************************************
809 iNADDR_ANY = ``INADDR_ANY''::_Word
810 sOMAXCONN = ``SOMAXCONN''::Int
811 maxListenQueue = sOMAXCONN
813 -------------------------------------------------------------------------------
814 shutdown :: Socket -> Int -> IO ()
815 shutdown (MkSocket s family stype protocol status) t =
816 primIOToIO (_ccall_ shutdown s t)
818 -------------------------------------------------------------------------------
820 sClose :: Socket -> IO ()
821 sClose (MkSocket s family stype protocol status) =
822 primIOToIO (_ccall_ close s)
824 -------------------------------------------------------------------------------
826 inet_addr :: String -> HostAddress
827 inet_addr ipstr = unsafePerformPrimIO (_ccall_ inet_addr ipstr)
829 -------------------------------------------------------------------------------
831 inet_ntoa :: HostAddress -> String
832 inet_ntoa haddr = unsafePerformPrimIO (
833 _casm_ ``struct in_addr addr;
834 addr.s_addr = htonl(%0);
835 %r = inet_ntoa (addr);'' haddr `thenPrimIO` \ str ->
836 returnPrimIO (_unpackPS (_packCString str)))
838 -------------------------------------------------------------------------------
840 sIsConnected :: Socket -> IO Bool
841 sIsConnected (MkSocket s family stype protocol status) =
842 readVar status `thenST` \ value ->
843 return (value == Connected)
845 -------------------------------------------------------------------------------
847 sIsBound :: Socket -> IO Bool
848 sIsBound (MkSocket s family stype protocol status) =
849 readVar status `thenST` \ value ->
850 return (value == Bound)
852 -------------------------------------------------------------------------------
854 sIsListening :: Socket -> IO Bool
855 sIsListening (MkSocket s family stype protocol status) =
856 readVar status `thenST` \ value ->
857 return (value == Listening)
859 -------------------------------------------------------------------------------
861 sIsReadable :: Socket -> IO Bool
862 sIsReadable (MkSocket s family stype protocol status) =
863 readVar status `thenST` \ value ->
864 return (value == Listening || value == Connected)
866 -------------------------------------------------------------------------------
868 sIsWritable :: Socket -> IO Bool
869 sIsWritable = sIsReadable
871 -------------------------------------------------------------------------------
873 sIsAcceptable :: Socket -> IO Bool
874 sIsAcceptable (MkSocket s AF_UNIX Stream protocol status) =
875 readVar status `thenST` \ value ->
876 return (value == Connected || value == Bound || value == Listening)
877 sIsAcceptable (MkSocket s AF_UNIX _ protocol status) =
879 sIsAcceptable (MkSocket s _ stype protocol status) =
880 readVar status `thenST` \ value ->
881 return (value == Connected || value == Listening)
883 -------------------------------------------------------------------------------
886 sSetBlocking :: Socket -> Bool -> IO ()
887 sIsBlocking :: Socket -> IO Bool
890 -------------------------------------------------------------------------------
892 allocSockAddr :: Family -> PrimIO (_MutableByteArray _RealWorld Int, Int)
893 allocSockAddr AF_UNIX =
894 newCharArray (0,``sizeof(struct sockaddr_un)'') `thenPrimIO` \ ptr ->
896 (_,sz) = boundsOfByteArray ptr
898 returnPrimIO (ptr, sz)
899 allocSockAddr AF_INET =
900 newCharArray (0,``sizeof(struct sockaddr_in)'') `thenPrimIO` \ ptr ->
902 (_,sz) = boundsOfByteArray ptr
904 returnPrimIO (ptr, sz)
906 -------------------------------------------------------------------------------
908 unpackSockAddr :: _MutableByteArray _RealWorld Int -> PrimIO SockAddr
910 _casm_ ``%r = ((struct sockaddr*)%0)->sa_family;'' arr `thenPrimIO` \ fam ->
911 case unpackFamily fam of
912 AF_UNIX -> unpackSockAddrUnix arr
913 AF_INET -> unpackSockAddrInet arr
915 -------------------------------------------------------------------------------
917 unpackSockAddrUnix :: (_MutableByteArray _RealWorld Int) -> PrimIO SockAddr
918 unpackSockAddrUnix ptr =
919 _casm_ ``%r = ((struct sockaddr_un*)%0)->sun_path;'' ptr
920 `thenPrimIO` \ str ->
921 strcpy str `thenPrimIO` \ path ->
922 returnPrimIO (SockAddrUnix path)
924 -------------------------------------------------------------------------------
926 unpackSockAddrInet :: (_MutableByteArray _RealWorld Int) -> PrimIO SockAddr
927 unpackSockAddrInet ptr =
928 _casm_ ``%r = ntohs(((struct sockaddr_in*)%0)->sin_port);'' ptr
929 `thenPrimIO` \ port ->
930 _casm_ ``%r = ntohl(((struct sockaddr_in*)%0)->sin_addr.s_addr);'' ptr
931 `thenPrimIO` \ address ->
932 returnPrimIO (SockAddrInet port address)
934 -------------------------------------------------------------------------------
937 packSockAddr :: SockAddr -> PrimIO (_MutableByteArray _RealWorld Int)
938 packSockAddr (SockAddrUnix path) =
939 allocSockAddr AF_UNIX `thenPrimIO` \ (ptr,_) ->
940 _casm_ ``(((struct sockaddr_un *)%0)->sun_family) = AF_UNIX;''
941 ptr `thenPrimIO` \ () ->
942 _casm_ ``strcpy ((((struct sockaddr_un *)%0)->sun_path),%1);''
943 ptr path `thenPrimIO` \ () ->
946 packSockAddr (SockAddrInet port address) =
947 allocSockAddr AF_INET `thenPrimIO` \ (ptr,_) ->
948 _casm_ ``(((struct sockaddr_in *)%0)->sin_family) = AF_INET;''
949 ptr `thenPrimIO` \ () ->
950 _casm_ ``(((struct sockaddr_in *)%0)->sin_port) = htons((int)%1);''
951 ptr port `thenPrimIO` \ () ->
952 _casm_ ``(((struct sockaddr_in *)%0)->sin_addr.s_addr) = htonl(%1);''
953 ptr address `thenPrimIO` \ () ->
956 -------------------------------------------------------------------------------
958 socketToHandle :: Socket -> IO Handle
959 socketToHandle (MkSocket s family stype protocol status) =
960 _casm_ ``%r = fdopen (%0, "r+");'' s `thenPrimIO` \ ptr ->
961 newEmptyMVar >>= \ handle ->
962 putMVar handle (_SocketHandle ptr False) >>
965 -------------------------------------------------------------------------------