1 | #include <stdio.h> |
---|
2 | #include <stdlib.h> |
---|
3 | #include <fcntl.h> |
---|
4 | #include <unistd.h> |
---|
5 | #include <sys/ioctl.h> |
---|
6 | #include <sys/stat.h> |
---|
7 | #include <sys/types.h> |
---|
8 | #include <sys/time.h> |
---|
9 | #include <string.h> |
---|
10 | #include <signal.h> |
---|
11 | #include <netinet/in.h> |
---|
12 | #include <sys/socket.h> |
---|
13 | |
---|
14 | #ifdef __sgi |
---|
15 | #include <bstring.h> |
---|
16 | #endif |
---|
17 | |
---|
18 | #ifdef _AIX |
---|
19 | #include <sys/select.h> |
---|
20 | #include <strings.h> |
---|
21 | extern "C" { |
---|
22 | #endif |
---|
23 | #include <netdb.h> |
---|
24 | |
---|
25 | #ifdef _AIX |
---|
26 | } ; |
---|
27 | #endif |
---|
28 | |
---|
29 | #include "jnet.hpp" |
---|
30 | #include "macs.hpp" |
---|
31 | #include "jmalloc.hpp" |
---|
32 | |
---|
33 | int net_init(int protocol) |
---|
34 | { |
---|
35 | if (protocol==TCPIP_PROTOCOL) // UNIX always has TCPIP! |
---|
36 | return 1; |
---|
37 | else return 0; |
---|
38 | } |
---|
39 | |
---|
40 | |
---|
41 | out_socket::~out_socket() |
---|
42 | { ; } |
---|
43 | |
---|
44 | void net_uninit() { ; } |
---|
45 | |
---|
46 | char last_sock_err[200]; |
---|
47 | int current_sock_err=0; |
---|
48 | |
---|
49 | void set_sock_err(int x) { current_sock_err=x; } |
---|
50 | |
---|
51 | |
---|
52 | #define PK_BUFFER_SIZE 2000 |
---|
53 | |
---|
54 | |
---|
55 | |
---|
56 | class unix_out_socket : public out_socket |
---|
57 | { |
---|
58 | int fd; |
---|
59 | int type; // SOCK_DGRAM, or SOCK_STREAM |
---|
60 | public : |
---|
61 | uchar pk_buffer[PK_BUFFER_SIZE]; |
---|
62 | long pk_buffer_ro,pk_buffer_last; |
---|
63 | unix_out_socket(int FD) { fd=FD; pk_buffer_ro=pk_buffer_last=0; } |
---|
64 | unix_out_socket(); |
---|
65 | void fill_buffer(); |
---|
66 | int get_fd() { return fd; } |
---|
67 | virtual int try_connect(char *rhost, int port); |
---|
68 | virtual int ready_to_read(); |
---|
69 | virtual int ready_to_write(); |
---|
70 | virtual int send(packet &pk); |
---|
71 | virtual int get(packet &pk); |
---|
72 | virtual ~unix_out_socket(); |
---|
73 | } ; |
---|
74 | |
---|
75 | |
---|
76 | class unix_in_socket : public in_socket |
---|
77 | { |
---|
78 | int fd; |
---|
79 | sockaddr_in host; |
---|
80 | int port; |
---|
81 | public : |
---|
82 | unix_in_socket(int Port); |
---|
83 | virtual out_socket *check_for_connect(); |
---|
84 | virtual ~unix_in_socket(); |
---|
85 | } ; |
---|
86 | |
---|
87 | |
---|
88 | int unix_out_socket::ready_to_read() |
---|
89 | { |
---|
90 | if (pk_buffer_last>pk_buffer_ro) return 1; |
---|
91 | struct timeval tv={0,0}; |
---|
92 | fd_set set,ex_set; |
---|
93 | FD_ZERO(&set); |
---|
94 | FD_SET(fd,&set); |
---|
95 | |
---|
96 | FD_ZERO(&ex_set); |
---|
97 | FD_SET(fd,&ex_set); |
---|
98 | select(FD_SETSIZE,&set,NULL,&ex_set,&tv); // check for exception |
---|
99 | return (FD_ISSET(fd,&set) || FD_ISSET(fd,&ex_set)); |
---|
100 | } |
---|
101 | |
---|
102 | int unix_out_socket::ready_to_write() |
---|
103 | { |
---|
104 | struct timeval tv={0,0}; |
---|
105 | fd_set set,ex_set; |
---|
106 | FD_ZERO(&set); |
---|
107 | FD_SET(fd,&set); |
---|
108 | select(FD_SETSIZE,NULL,&set,NULL,&tv); // check for exception |
---|
109 | return (FD_ISSET(fd,&set)); |
---|
110 | } |
---|
111 | |
---|
112 | unix_in_socket::unix_in_socket(int Port) |
---|
113 | { |
---|
114 | port=Port; |
---|
115 | fd=socket(AF_INET,SOCK_STREAM,0); |
---|
116 | memset( (char*) &host,0, sizeof(host)); |
---|
117 | host.sin_family = AF_INET; |
---|
118 | host.sin_port = htons(port); |
---|
119 | host.sin_addr.s_addr = htonl (INADDR_ANY); |
---|
120 | if (bind(fd, (struct sockaddr *) &host, sizeof(sockaddr_in))==-1) |
---|
121 | { |
---|
122 | set_sock_err(SOCK_BIND_FAIL); |
---|
123 | sprintf(last_sock_err,"Unable to bind to port %d",port); |
---|
124 | } |
---|
125 | else |
---|
126 | { |
---|
127 | if (listen(fd,1)==-1) |
---|
128 | { |
---|
129 | set_sock_err(SOCK_LISTEN_FAIL); |
---|
130 | sprintf(last_sock_err,"Unable to listen to port %d",port); |
---|
131 | } |
---|
132 | } |
---|
133 | |
---|
134 | } |
---|
135 | |
---|
136 | |
---|
137 | out_socket *unix_in_socket::check_for_connect() |
---|
138 | { |
---|
139 | struct timeval tv={0,0}; |
---|
140 | fd_set set,ex_set; |
---|
141 | FD_ZERO(&set); |
---|
142 | FD_SET(fd,&set); |
---|
143 | |
---|
144 | |
---|
145 | select(FD_SETSIZE,&set,NULL,NULL,&tv); // check for exception |
---|
146 | |
---|
147 | if (FD_ISSET(fd,&set)) |
---|
148 | { |
---|
149 | int len=sizeof(sockaddr_in); |
---|
150 | int new_fd=accept(fd, (struct sockaddr *) &host, &len); |
---|
151 | if (new_fd<0) |
---|
152 | { |
---|
153 | set_sock_err(SOCK_ACCEPT_FAIL); |
---|
154 | sprintf(last_sock_err,"Accept failure on port %d",port); |
---|
155 | return NULL; |
---|
156 | } |
---|
157 | |
---|
158 | unsigned long gaddr=ntohl(host.sin_addr.s_addr); |
---|
159 | return new unix_out_socket(new_fd); |
---|
160 | } else return NULL; |
---|
161 | } |
---|
162 | |
---|
163 | |
---|
164 | unix_out_socket::unix_out_socket() |
---|
165 | { |
---|
166 | pk_buffer_ro=pk_buffer_last=0; |
---|
167 | fd=-1; |
---|
168 | } |
---|
169 | |
---|
170 | |
---|
171 | int unix_out_socket::try_connect(char *rhost, int port) |
---|
172 | { |
---|
173 | if (strlen(rhost)>5 && |
---|
174 | rhost[0]=='t' && |
---|
175 | rhost[1]=='c' && |
---|
176 | rhost[2]=='p' && |
---|
177 | rhost[1]=='/') |
---|
178 | type=SOCK_STREAM; |
---|
179 | else type=SOCK_DGRAM; |
---|
180 | |
---|
181 | if (fd==-1) |
---|
182 | fd=socket(AF_INET,type,0); |
---|
183 | if (fd==-1) |
---|
184 | { |
---|
185 | set_sock_err(SOCK_CREATE_FAIL); |
---|
186 | sprintf(last_sock_err,"Failed to create socket (too many file descriptors open?)"); |
---|
187 | return 0; |
---|
188 | } |
---|
189 | |
---|
190 | hostent *hp=gethostbyname(rhost); |
---|
191 | if (!rhost) |
---|
192 | { |
---|
193 | set_sock_err(SOCK_NAMELOOKUP_FAIL); |
---|
194 | sprintf(last_sock_err,"Unable to get address for name %s",rhost); |
---|
195 | return 0; |
---|
196 | } else |
---|
197 | { |
---|
198 | sockaddr_in host; |
---|
199 | memset( (char*) &host,0, sizeof(host)); |
---|
200 | host.sin_family = AF_INET; |
---|
201 | host.sin_port = htons(port); |
---|
202 | host.sin_addr.s_addr = htonl (INADDR_ANY); |
---|
203 | memcpy(&host.sin_addr,hp->h_addr,hp->h_length); |
---|
204 | |
---|
205 | if (connect(fd, (struct sockaddr *) &host, sizeof(host))==-1) |
---|
206 | { |
---|
207 | set_sock_err(SOCK_CONNECT_FAIL); |
---|
208 | sprintf(last_sock_err,"Unable to connect to address %s on port %d",rhost,port); |
---|
209 | return 0; |
---|
210 | } |
---|
211 | |
---|
212 | return 1; |
---|
213 | } |
---|
214 | } |
---|
215 | |
---|
216 | |
---|
217 | |
---|
218 | unix_out_socket::~unix_out_socket() |
---|
219 | { close(fd); } |
---|
220 | |
---|
221 | unix_in_socket::~unix_in_socket() |
---|
222 | { close(fd); } |
---|
223 | |
---|
224 | |
---|
225 | void unix_out_socket::fill_buffer() |
---|
226 | { |
---|
227 | while (!ready_to_read()) ; |
---|
228 | pk_buffer_last=read(get_fd(),pk_buffer,PK_BUFFER_SIZE); |
---|
229 | pk_buffer_ro=0; |
---|
230 | } |
---|
231 | |
---|
232 | int unix_out_socket::get(packet &pk) |
---|
233 | { |
---|
234 | pk.ro=pk.wo=2; |
---|
235 | |
---|
236 | ushort size=0; |
---|
237 | if (pk_buffer_last==pk_buffer_ro) |
---|
238 | fill_buffer(); |
---|
239 | |
---|
240 | if (pk_buffer_last-pk_buffer_ro<2) // make sure the two byte for the size are in the same packet |
---|
241 | { |
---|
242 | uchar two[2]; |
---|
243 | two[0]=pk_buffer[pk_buffer_ro]; |
---|
244 | fill_buffer(); |
---|
245 | if (pk_buffer_last-pk_buffer_ro<2) // if still not enough info, something is screwy |
---|
246 | { |
---|
247 | printf("Incomplete packet\n"); |
---|
248 | return 0; |
---|
249 | } |
---|
250 | |
---|
251 | two[1]=pk_buffer[pk_buffer_ro]; |
---|
252 | pk_buffer_ro++; |
---|
253 | size=lstl((*((ushort *)two))); |
---|
254 | } else |
---|
255 | { |
---|
256 | memcpy(&size,pk_buffer+pk_buffer_ro,2); pk_buffer_ro+=2; |
---|
257 | size=lstl(size); |
---|
258 | } |
---|
259 | pk.rend=size+2; |
---|
260 | pk.make_bigger(pk.rend); |
---|
261 | |
---|
262 | uchar *pk_off=pk.buf+2; |
---|
263 | int rs; |
---|
264 | while (size) |
---|
265 | { |
---|
266 | if (pk_buffer_last==pk_buffer_ro) |
---|
267 | fill_buffer(); |
---|
268 | if (pk_buffer_last-pk_buffer_ro>size) |
---|
269 | rs=size; |
---|
270 | else |
---|
271 | rs=pk_buffer_last-pk_buffer_ro; |
---|
272 | |
---|
273 | memcpy(pk_off,pk_buffer+pk_buffer_ro,rs); |
---|
274 | pk_buffer_ro+=rs; |
---|
275 | size-=rs; |
---|
276 | pk_off+=rs; |
---|
277 | } |
---|
278 | |
---|
279 | return 1; |
---|
280 | } |
---|
281 | |
---|
282 | int unix_out_socket::send(packet &pk) |
---|
283 | { |
---|
284 | while (!ready_to_write()) ; |
---|
285 | ushort size=lstl(pk.wo-2); |
---|
286 | memcpy(pk.buf,&size,2); |
---|
287 | return write(fd,pk.buf,pk.wo)==pk.wo; |
---|
288 | } |
---|
289 | |
---|
290 | in_socket *create_in_socket(int port) |
---|
291 | { return new unix_in_socket(port); } |
---|
292 | |
---|
293 | out_socket *create_out_socket(char *name, int port) |
---|
294 | { unix_out_socket *s=new unix_out_socket(); |
---|
295 | if (s->try_connect(name,port)) |
---|
296 | return s; |
---|
297 | else |
---|
298 | delete s; |
---|
299 | return NULL; |
---|
300 | } |
---|
301 | |
---|
302 | uchar *get_local_address() // same format as above (be sure to jfree this) |
---|
303 | { |
---|
304 | char name[80]; |
---|
305 | uchar *ip=(uchar *)jmalloc(4,"IP address"); |
---|
306 | |
---|
307 | if (gethostname(name,80)!=0) |
---|
308 | { ip[0]=127; ip[1]=ip[2]=0; ip[3]=1; } |
---|
309 | else |
---|
310 | { |
---|
311 | struct hostent *me=gethostbyname(name); |
---|
312 | memcpy(ip,me->h_addr,4); |
---|
313 | } |
---|
314 | } |
---|
315 | |
---|
316 | |
---|
317 | |
---|
318 | |
---|
319 | |
---|
320 | |
---|
321 | |
---|
322 | |
---|
323 | |
---|