-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathffsocket.nit
More file actions
212 lines (193 loc) · 6.96 KB
/
ffsocket.nit
File metadata and controls
212 lines (193 loc) · 6.96 KB
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
module ffsocket
in "C Header" `{
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
typedef int S_DESCRIPTOR;
typedef struct sockaddr_in S_ADDR_IN;
typedef struct sockaddr S_ADDR;
typedef struct in_addr S_IN_ADDR;
typedef struct hostent S_HOSTENT;
typedef struct timeval S_TIMEVAL;
typedef struct sockaccept_result { S_ADDR_IN addr_in; S_DESCRIPTOR s_desc; } S_ACCEPT_RESULT;
typedef fd_set S_FD_SET;
typedef socklen_t S_LEN;
`}
extern FFSocket `{ S_DESCRIPTOR* `}
new socket(domain :FFSocketAddressFamilies, socketType :FFSocketTypes, protocol :FFSocketProtocolFamilies) `{
S_DESCRIPTOR *d = NULL; d = (S_DESCRIPTOR*) malloc( sizeof(S_DESCRIPTOR) );
int ds = socket(domain, socketType, protocol);
memcpy(d, &ds, sizeof(ds));
return d;
`}
fun destroy `{ free(recv); `}
fun close:Int `{ return close( *recv ); `}
fun descriptor:Int `{ return *recv; `}
fun errno:Int `{ return errno; `}
private fun i_gethostbyname(n: NativeString):FFSocketHostent import String::to_cstring `{ return gethostbyname(n); `}
fun gethostbyname(name: String):FFSocketHostent do return i_gethostbyname(name.to_cstring)
private fun i_connect(addrIn: FFSocketAddrIn):Int `{ return connect( *recv, (S_ADDR*)addrIn, sizeof(*addrIn) ); `}
fun connect(addrIn: FFSocketAddrIn):Int do return i_connect(addrIn)
private fun i_write(buffer: String, length: Int):Int import String::to_cstring `{ return write(*recv, (char*)String_to_cstring(buffer), length);`}
fun write(buffer: String):Int do return i_write(buffer, buffer.length)
private fun i_read:String `{
char c[1024];
int n = read(*recv, c, (sizeof(c)-1));
if(n < 0) exit(-1);
c[n] = '\0';
return new_String_from_cstring(c);
`}
fun read:String do return i_read
private fun i_bind(addrIn: FFSocketAddrIn):Int `{ return bind(*recv, (S_ADDR*)addrIn, sizeof(*addrIn)); `}
fun bind(addrIn: FFSocketAddrIn):Int do return i_bind(addrIn)
private fun i_listen(size: Int):Int `{ return listen(*recv, size); `}
fun listen(size: Int):Int do return i_listen(size)
private fun i_accept(addrIn: FFSocketAddrIn):FFSocket `{
S_LEN s = sizeof(S_ADDR);
S_DESCRIPTOR *d = NULL;
d = malloc(sizeof(S_DESCRIPTOR*));
*d = accept(*recv,(S_ADDR*)addrIn, &s);
return d;
`}
fun accept:FFSocketAcceptResult
do
var addrIn = new FFSocketAddrIn
var s = i_accept(addrIn)
return new FFSocketAcceptResult(s, addrIn)
end
end
extern FFSocketAcceptResult `{ S_ACCEPT_RESULT* `}
new (socket: FFSocket, addrIn: FFSocketAddrIn) `{
S_ACCEPT_RESULT *sar = NULL;
sar = malloc( sizeof(S_ACCEPT_RESULT*) );
sar->s_desc = *socket;
sar->addr_in = *addrIn;
return sar;
`}
fun socket:FFSocket `{ return &recv->s_desc; `}
fun addrIn:FFSocketAddrIn `{ return &recv->addr_in; `}
fun destroy `{ free(recv); `}
end
extern FFSocketAddrIn `{ S_ADDR_IN* `}
new `{
S_ADDR_IN *sai = NULL;
sai = malloc( sizeof(S_ADDR_IN*) );
return sai;
`}
new with(port: Int, family: FFSocketAddressFamilies) `{
S_ADDR_IN *sai = NULL;
sai = malloc( sizeof(S_ADDR_IN*) );
sai->sin_family = family;
sai->sin_port = htons(port);
sai->sin_addr.s_addr = INADDR_ANY;
return sai;
`}
new withHostent(hostent: FFSocketHostent, port: Int) `{
S_ADDR_IN *sai = NULL;
sai = malloc( sizeof(S_ADDR_IN*) );
sai->sin_family = hostent->h_addrtype;
sai->sin_port = htons(port);
memcpy( (char*)&sai->sin_addr.s_addr, (char*)hostent->h_addr, hostent->h_length );
return sai;
`}
fun address:String `{ return new_String_from_cstring( (char*)inet_ntoa(recv->sin_addr) ); `}
fun family:FFSocketAddressFamilies `{ return recv->sin_family; `}
fun port:Int `{ return ntohs(recv->sin_port); `}
fun destroy `{ free(recv); `}
end
extern FFSocketHostent `{ S_HOSTENT* `}
private fun i_h_aliases(i:Int):String `{ return new_String_from_cstring(recv->h_aliases[i]); `}
private fun i_h_aliases_reachable(i:Int):Bool `{ return (recv->h_aliases[i] != NULL); `}
fun h_aliases:Array[String]
do
var i=0
var d=new Array[String]
loop
d.add(i_h_aliases(i))
if i_h_aliases_reachable(i+1) == false then break
i += 1
end
return d
end
fun h_addr:String `{ return new_String_from_cstring( (char*)inet_ntoa(*(S_IN_ADDR*)recv->h_addr) ); `}
fun h_addrtype:Int `{ return recv->h_addrtype; `}
fun h_length:Int `{ return recv->h_length; `}
fun h_name:String `{ return new_String_from_cstring(recv->h_name); `}
end
extern FFTimeval `{ S_TIMEVAL* `}
new (seconds: Int, microseconds: Int) `{
S_TIMEVAL* tv = NULL;
tv = malloc( sizeof(S_TIMEVAL*) );
tv->tv_sec = seconds;
tv->tv_usec = microseconds;
return tv;
`}
fun seconds:Int `{ return recv->tv_sec; `}
fun microseconds:Int `{ return recv->tv_usec; `}
fun destroy `{ free( recv ); `}
end
extern FFSocketSet `{ S_FD_SET* `}
new `{
S_FD_SET *f = NULL;
f = malloc( sizeof(S_FD_SET*) );
return f;
`}
fun set(s: FFSocket) `{ FD_SET( *s, recv ); `}
fun isSet(s: FFSocket):Bool `{ return FD_ISSET( *s, recv ); `}
fun zero `{ FD_ZERO( recv ); `}
fun clear(s: FFSocket) `{ FD_CLR( *s, recv ); `}
fun destroy `{ free( recv ); `}
end
class FFSocketObserver
fun select(max: FFSocket, reads: nullable FFSocketSet, write: nullable FFSocketSet, except: nullable FFSocketSet, timeout: FFTimeval):Int `{
S_FD_SET *rds, *wts, *exs = NULL;
S_TIMEVAL *tm = NULL;
if(reads != NULL) rds = (S_FD_SET*)reads;
if(write != NULL) wts = (S_FD_SET*)write;
if(except != NULL) exs = (S_FD_SET*)except;
if(timeout != NULL) tm = (S_TIMEVAL*)timeout;
return select(*max, rds, wts, exs, tm);
`}
end
extern FFSocketTypes `{ int `}
new sock_stream `{ return SOCK_STREAM; `}
new sock_dgram `{ return SOCK_DGRAM; `}
new sock_raw `{ return SOCK_RAW; `}
new sock_seqpacket `{ return SOCK_SEQPACKET; `}
end
extern FFSocketAddressFamilies `{ int `}
new af_null `{ return 0; `}
new af_unspec `{ return AF_UNSPEC; `} # unspecified
new af_unix `{ return AF_UNIX; `} # local to host (pipes)
new af_local `{ return AF_LOCAL; `} # backward compatibility
new af_inet `{ return AF_INET; `} # internetwork: UDP, TCP, etc.
new af_sna `{ return AF_SNA; `} # IBM SNA
new af_decnet `{ return AF_DECnet; `} # DECnet
new af_route `{ return AF_ROUTE; `} # Internal Routing Protocol
new af_ipx `{ return AF_IPX; `} # Novell Internet Protocol
new af_isdn `{ return AF_ISDN; `} # Integrated Services Digital Network
new af_inet6 `{ return AF_INET6; `} # IPv6
new af_max `{ return AF_MAX; `}
end
extern FFSocketProtocolFamilies `{ int `}
new pf_null `{ return 0; `}
new pf_unspec `{ return PF_UNSPEC; `}
new pf_local `{ return PF_LOCAL; `}
new pf_unix `{ return PF_UNIX; `}
new pf_inet `{ return PF_INET; `}
new pf_sna `{ return PF_SNA; `}
new pf_decnet `{ return PF_DECnet; `}
new pf_route `{ return PF_ROUTE; `}
new pf_ipx `{ return PF_IPX; `}
new pf_isdn `{ return PF_ISDN; `}
new pf_key `{ return PF_KEY; `}
new pf_inet6 `{ return PF_INET6; `}
new pf_max `{ return PF_MAX; `}
end