b6c7740b394028f456609b01494174e3b0564fa6
[nit.git] / lib / socket / socket.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2013 Matthieu Lucas <lucasmatthieu@gmail.com>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Socket services
18 module socket
19
20 import socket_c
21
22 class Socket
23 var address: String
24 var host: nullable String
25 var port: Int
26 private var socket: FFSocket
27 private var addrin: FFSocketAddrIn
28
29 init stream_with_host(thost: String, tport: Int)
30 do
31 socket = new FFSocket.socket( new FFSocketAddressFamilies.af_inet, new FFSocketTypes.sock_stream, new FFSocketProtocolFamilies.pf_null )
32 var hostname = socket.gethostbyname(thost)
33 addrin = new FFSocketAddrIn.with_hostent(hostname, tport)
34 address = addrin.address
35 host = hostname.h_name
36 port = addrin.port
37 end
38
39 init stream_with_port(tport: Int)
40 do
41 socket = new FFSocket.socket( new FFSocketAddressFamilies.af_inet, new FFSocketTypes.sock_stream, new FFSocketProtocolFamilies.pf_null )
42 addrin = new FFSocketAddrIn.with(tport, new FFSocketAddressFamilies.af_inet)
43 address = addrin.address
44 port = addrin.port
45 host = null
46 end
47
48 init primitive_init(h: FFSocketAcceptResult)
49 do
50 socket = h.socket
51 addrin = h.addrIn
52 address = addrin.address
53 port = addrin.port
54 host = null
55 end
56
57 # Returns an array containing an enum of the events ready to be read
58 #
59 # event_types : Combination of several event types to watch
60 #
61 # timeout : Time in milliseconds before stopping listening for events on this socket
62 #
63 private fun poll_in(event_types: Array[FFSocketPollValues], timeout: Int): Array[FFSocketPollValues] do return socket.socket_poll(new PollFD(socket.descriptor, event_types), timeout)
64
65 # Easier use of poll_in to check for something to read on all channels of any priority
66 #
67 # timeout : Time in milliseconds before stopping to wait for events
68 #
69 fun ready_to_read(timeout: Int): Bool
70 do
71 var events = new Array[FFSocketPollValues]
72 events.push(new FFSocketPollValues.pollin)
73 events.push(new FFSocketPollValues.pollrdnorm)
74 events.push(new FFSocketPollValues.pollpri)
75 events.push(new FFSocketPollValues.pollrdband)
76 return poll_in(events, timeout).length != 0
77 end
78
79 # Checks if the socket still is connected
80 #
81 fun connected: Bool
82 do
83 var events = new Array[FFSocketPollValues]
84 events.push(new FFSocketPollValues.pollhup)
85 events.push(new FFSocketPollValues.pollerr)
86 return poll_in(events, 0).length == 0
87 end
88
89 fun connect: Bool do return socket.connect(addrin) >= 0
90 fun write(msg: String): Bool do return socket.write(msg) >= 0
91 fun read: String do return socket.read
92 fun close: Bool do return socket.close >= 0
93 fun bind: Bool do return socket.bind(addrin) >= 0
94 fun listen(size: Int): Bool do return socket.listen(size) >= 0
95 fun accept: Socket do return new Socket.primitive_init(socket.accept)
96 fun errno: Int do return socket.errno
97 end
98
99 class SocketSet
100 var sset: FFSocketSet
101 init do sset = new FFSocketSet end
102 fun set(s: Socket) do sset.set(s.socket) end
103 fun is_set(s: Socket): Bool do return sset.is_set(s.socket) end
104 fun zero do sset.zero end
105 fun clear(s: Socket) do sset.clear(s.socket) end
106 end
107
108 class SocketObserver
109 private var observer: FFSocketObserver
110 var readset: nullable SocketSet = null
111 var writeset: nullable SocketSet = null
112 var exceptset: nullable SocketSet = null
113 init(read :Bool, write :Bool, except: Bool)
114 do
115 if read then readset = new SocketSet
116 if write then writeset = new SocketSet
117 if except then exceptset = new SocketSet
118 observer = new FFSocketObserver
119 end
120 fun select(max: Socket,seconds: Int, microseconds: Int): Bool
121 do
122 var timeval = new FFTimeval(seconds, microseconds)
123 return observer.select(max.socket, readset.sset, writeset.sset, readset.sset, timeval) > 0
124 end
125 end
126