nitg: add option --global
[nit.git] / lib / socket / socket_c.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 # Low-level socket functionalities
18 module socket_c
19
20 in "C Header" `{
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <sys/socket.h>
26 #include <sys/types.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
29 #include <netdb.h>
30 #include <errno.h>
31
32 typedef int S_DESCRIPTOR;
33 typedef struct sockaddr_in S_ADDR_IN;
34 typedef struct sockaddr S_ADDR;
35 typedef struct in_addr S_IN_ADDR;
36 typedef struct hostent S_HOSTENT;
37 typedef struct timeval S_TIMEVAL;
38 typedef struct sockaccept_result { S_ADDR_IN addr_in; S_DESCRIPTOR s_desc; } S_ACCEPT_RESULT;
39 typedef fd_set S_FD_SET;
40 typedef socklen_t S_LEN;
41 `}
42
43 extern FFSocket `{ S_DESCRIPTOR* `}
44 new socket(domain: FFSocketAddressFamilies, socketType: FFSocketTypes, protocol: FFSocketProtocolFamilies) `{
45 S_DESCRIPTOR *d = NULL; d = (S_DESCRIPTOR*) malloc( sizeof(S_DESCRIPTOR) );
46 int ds = socket(domain, socketType, protocol);
47 memcpy(d, &ds, sizeof(ds));
48 return d;
49 `}
50 fun destroy `{ free(recv); `}
51 fun close: Int `{ return close( *recv ); `}
52 fun descriptor: Int `{ return *recv; `}
53 fun errno: Int `{ return errno; `}
54
55 fun gethostbyname(n: String): FFSocketHostent import String::to_cstring `{ return gethostbyname(String_to_cstring(n)); `}
56 fun connect(addrIn: FFSocketAddrIn): Int `{ return connect( *recv, (S_ADDR*)addrIn, sizeof(*addrIn) ); `}
57 fun write(buffer: String): Int import String::to_cstring, String::length `{ return write(*recv, (char*)String_to_cstring(buffer), String_length(buffer)); `}
58
59 fun read: String `{
60 char c[1024];
61 int n = read(*recv, c, (sizeof(c)-1));
62 if(n < 0) exit(-1);
63 c[n] = '\0';
64 return new_String_from_cstring(c);
65 `}
66
67 fun bind(addrIn: FFSocketAddrIn): Int `{ return bind(*recv, (S_ADDR*)addrIn, sizeof(*addrIn)); `}
68 fun listen(size: Int): Int `{ return listen(*recv, size); `}
69
70 private fun i_accept(addrIn: FFSocketAddrIn): FFSocket `{
71 S_LEN s = sizeof(S_ADDR);
72 S_DESCRIPTOR *d = NULL;
73 d = malloc(sizeof(S_DESCRIPTOR*));
74 *d = accept(*recv,(S_ADDR*)addrIn, &s);
75 return d;
76 `}
77 fun accept: FFSocketAcceptResult
78 do
79 var addrIn = new FFSocketAddrIn
80 var s = i_accept(addrIn)
81 return new FFSocketAcceptResult(s, addrIn)
82 end
83 end
84
85 extern FFSocketAcceptResult `{ S_ACCEPT_RESULT* `}
86 new (socket: FFSocket, addrIn: FFSocketAddrIn) `{
87 S_ACCEPT_RESULT *sar = NULL;
88 sar = malloc( sizeof(S_ACCEPT_RESULT*) );
89 sar->s_desc = *socket;
90 sar->addr_in = *addrIn;
91 return sar;
92 `}
93 fun socket: FFSocket `{ return &recv->s_desc; `}
94 fun addrIn: FFSocketAddrIn `{ return &recv->addr_in; `}
95 fun destroy `{ free(recv); `}
96 end
97
98 extern FFSocketAddrIn `{ S_ADDR_IN* `}
99 new `{
100 S_ADDR_IN *sai = NULL;
101 sai = malloc( sizeof(S_ADDR_IN*) );
102 return sai;
103 `}
104 new with(port: Int, family: FFSocketAddressFamilies) `{
105 S_ADDR_IN *sai = NULL;
106 sai = malloc( sizeof(S_ADDR_IN*) );
107 sai->sin_family = family;
108 sai->sin_port = htons(port);
109 sai->sin_addr.s_addr = INADDR_ANY;
110 return sai;
111 `}
112 new with_hostent(hostent: FFSocketHostent, port: Int) `{
113 S_ADDR_IN *sai = NULL;
114 sai = malloc( sizeof(S_ADDR_IN*) );
115 sai->sin_family = hostent->h_addrtype;
116 sai->sin_port = htons(port);
117 memcpy( (char*)&sai->sin_addr.s_addr, (char*)hostent->h_addr, hostent->h_length );
118 return sai;
119 `}
120 fun address: String `{ return new_String_from_cstring( (char*)inet_ntoa(recv->sin_addr) ); `}
121 fun family: FFSocketAddressFamilies `{ return recv->sin_family; `}
122 fun port: Int `{ return ntohs(recv->sin_port); `}
123 fun destroy `{ free(recv); `}
124 end
125
126 extern FFSocketHostent `{ S_HOSTENT* `}
127 private fun i_h_aliases(i: Int): String `{ return new_String_from_cstring(recv->h_aliases[i]); `}
128 private fun i_h_aliases_reachable(i: Int): Bool `{ return (recv->h_aliases[i] != NULL); `}
129 fun h_aliases: Array[String]
130 do
131 var i=0
132 var d=new Array[String]
133 loop
134 d.add(i_h_aliases(i))
135 if i_h_aliases_reachable(i+1) == false then break
136 i += 1
137 end
138 return d
139 end
140 fun h_addr: String `{ return new_String_from_cstring( (char*)inet_ntoa(*(S_IN_ADDR*)recv->h_addr) ); `}
141 fun h_addrtype: Int `{ return recv->h_addrtype; `}
142 fun h_length: Int `{ return recv->h_length; `}
143 fun h_name: String `{ return new_String_from_cstring(recv->h_name); `}
144 end
145
146 extern FFTimeval `{ S_TIMEVAL* `}
147 new (seconds: Int, microseconds: Int) `{
148 S_TIMEVAL* tv = NULL;
149 tv = malloc( sizeof(S_TIMEVAL*) );
150 tv->tv_sec = seconds;
151 tv->tv_usec = microseconds;
152 return tv;
153 `}
154 fun seconds: Int `{ return recv->tv_sec; `}
155 fun microseconds: Int `{ return recv->tv_usec; `}
156 fun destroy `{ free( recv ); `}
157 end
158
159 extern FFSocketSet `{ S_FD_SET* `}
160 new `{
161 S_FD_SET *f = NULL;
162 f = malloc( sizeof(S_FD_SET*) );
163 return f;
164 `}
165 fun set(s: FFSocket) `{ FD_SET( *s, recv ); `}
166 fun is_set(s: FFSocket): Bool `{ return FD_ISSET( *s, recv ); `}
167 fun zero `{ FD_ZERO( recv ); `}
168 fun clear(s: FFSocket) `{ FD_CLR( *s, recv ); `}
169 fun destroy `{ free( recv ); `}
170 end
171
172 class FFSocketObserver
173 fun select(max: FFSocket, reads: nullable FFSocketSet, write: nullable FFSocketSet,
174 except: nullable FFSocketSet, timeout: FFTimeval): Int `{
175 S_FD_SET *rds, *wts, *exs = NULL;
176 S_TIMEVAL *tm = NULL;
177 if(reads != NULL) rds = (S_FD_SET*)reads;
178 if(write != NULL) wts = (S_FD_SET*)write;
179 if(except != NULL) exs = (S_FD_SET*)except;
180 if(timeout != NULL) tm = (S_TIMEVAL*)timeout;
181 return select(*max, rds, wts, exs, tm);
182 `}
183 end
184
185 extern FFSocketTypes `{ int `}
186 new sock_stream `{ return SOCK_STREAM; `}
187 new sock_dgram `{ return SOCK_DGRAM; `}
188 new sock_raw `{ return SOCK_RAW; `}
189 new sock_seqpacket `{ return SOCK_SEQPACKET; `}
190 end
191 extern FFSocketAddressFamilies `{ int `}
192 new af_null `{ return 0; `}
193 new af_unspec `{ return AF_UNSPEC; `} # unspecified
194 new af_unix `{ return AF_UNIX; `} # local to host (pipes)
195 new af_local `{ return AF_LOCAL; `} # backward compatibility
196 new af_inet `{ return AF_INET; `} # internetwork: UDP, TCP, etc.
197 new af_sna `{ return AF_SNA; `} # IBM SNA
198 new af_decnet `{ return AF_DECnet; `} # DECnet
199 new af_route `{ return AF_ROUTE; `} # Internal Routing Protocol
200 new af_ipx `{ return AF_IPX; `} # Novell Internet Protocol
201 new af_isdn `{ return AF_ISDN; `} # Integrated Services Digital Network
202 new af_inet6 `{ return AF_INET6; `} # IPv6
203 new af_max `{ return AF_MAX; `}
204 end
205 extern FFSocketProtocolFamilies `{ int `}
206 new pf_null `{ return 0; `}
207 new pf_unspec `{ return PF_UNSPEC; `}
208 new pf_local `{ return PF_LOCAL; `}
209 new pf_unix `{ return PF_UNIX; `}
210 new pf_inet `{ return PF_INET; `}
211 new pf_sna `{ return PF_SNA; `}
212 new pf_decnet `{ return PF_DECnet; `}
213 new pf_route `{ return PF_ROUTE; `}
214 new pf_ipx `{ return PF_IPX; `}
215 new pf_isdn `{ return PF_ISDN; `}
216 new pf_key `{ return PF_KEY; `}
217 new pf_inet6 `{ return PF_INET6; `}
218 new pf_max `{ return PF_MAX; `}
219 end
220