1 /**************************************************************************
2 * X J D C L I E N T * *
3 * Code for Interfacing the Client with the server *
4 * Japanese-English Dictionary program (X11 version) *
5 * Author: Jim Breen *
6 ***************************************************************************/
7 /* This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 1, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 /* for Solaris 2.5, which doesn't have INADDR_NONE in its <netinet/in.h> */
22 #ifdef SOLARIS
23 #define INADDR_NONE -1
24 #endif
25
26
27 #include <stdio.h>
28 #include <ctype.h>
29 #include <string.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <netdb.h>
34 #include <sys/stat.h>
35 #include <sys/time.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <signal.h>
39 #include "xjdic.h"
40
41 #define CVERBOSE 0
42 int chk_cnt=0;
43 #ifdef __DragonFly__
44 #include <arpa/inet.h>
45 #include <errno.h>
46 #else
47 extern int errno;
48 #endif
49 unsigned char host[51] = {"localhost"};
50 unsigned char yn[2];
51 unsigned int portno = XJ_PORTNO;
52 char protocol[4] = {"udp"};
53 int s, elapse;
54 struct timeval timeout;
55 int txno = 0;
56
57 REQ_PDU pdu_out;
58 RSP_PDU pdu_in;
59 int pduseq = 0;
60 int curr_timer = TINITVAL;
61 int rep_count;
62 struct timezone tz;
63 long timeofday_st,timeofday_en;
64 fd_set fildesc;
65 int nfds;
66 unsigned char *sptr;
67 int NoDics,CurrDic;
68 char Dnamet[10][100];
69
70 void xjdserver (int type, int dic_no, long index_posn, int sch_str_len,
71 unsigned char *sch_str, int *sch_resp, long *res_index,
72 int *hit_posn, int *res_len, unsigned char *res_str,
73 long *dic_loc );
74 void DicSet();
75 int connectsock(int portno, char *host);
76 void reqchecksum();
77 int respchecksum();
78
DicSet()79 void DicSet()
80 {
81 /* In the Client version, DicSet() establishes the connection with
82 the server. */
83
84 int i,schresp, dumint, trying,hullodic;
85 long dumlong,dumlong0 = 0;
86 char dummy[2],dnamelist[512];
87
88 connectsock(portno, host);
89 nfds = getdtablesize();
90 FD_SET(s, &fildesc);
91 trying = TRUE;
92 while (trying)
93 {
94 xjdserver(XJ_HULLO, 0, dumlong0, 0, dummy, &schresp, &dumlong,
95 &hullodic, &dumint, dnamelist, &dumlong);
96 if (schresp == XJ_OK)
97 {
98 printf("Server: %s detected\n", host);
99 NoDics = hullodic;
100 sptr = strtok(dnamelist,"#");
101 while (sptr != NULL)
102 {
103 i = sptr[0] - '0';
104 if (i <= NoDics)
105 {
106 strcpy(Dnamet[i],sptr+1);
107 printf ("Dictionary: %d [%s]\n",i,Dnamet[i]);
108 }
109 sptr = strtok(NULL,"#");
110 }
111 CurrDic = 1;
112 return;
113 }
114 printf("Server not responding.(%d) Try again? (y/n)",schresp);
115 scanf("%c",dummy);
116 printf("\n");
117 if ((dummy[0] | 0x20) == 'n') exit(1);
118 }
119 }
120
connectsock(int portno,char * host)121 int connectsock(int portno, char *host)
122 {
123
124 struct protoent *ppe;
125 struct hostent *phe;
126 struct sockaddr_in sin;
127
128 bzero((char *)&sin, sizeof(sin));
129 sin.sin_family = AF_INET;
130 sin.sin_port = htons(portno);
131 if (phe = gethostbyname(host))
132 bcopy(phe->h_addr, (char *)&sin.sin_addr, phe->h_length);
133 else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
134 {
135 printf ("Cannot Get Host Entry!!\n");
136 exit(1);
137 }
138 if ((ppe = getprotobyname("udp")) == 0)
139 {
140 printf ("Cannot set up UDP!!\n");
141 exit(1);
142 }
143 s = socket(PF_INET, SOCK_DGRAM, ppe->p_proto);
144 if (s < 0)
145 {
146 printf ("Cannot create socket!!: %s\n",strerror(errno));
147 exit(1);
148 }
149 if (connect (s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
150 {
151 printf ("Cannot connect to host: %s, port: %d\n",host,portno);
152 exit(1);
153 }
154
155 return (s);
156 }
157
respchecksum()158 int respchecksum()
159 {
160 long temp;
161 int i;
162 char yn[5];
163
164 if (CVERBOSE) printf("PDU: %d %d %d %d %d %d %s %d\n",
165 ntohs(pdu_in.xjdrsp_type),
166 ntohs(pdu_in.xjdrsp_seq),
167 ntohl(pdu_in.xjdrsp_resindex),
168 ntohl(pdu_in.xjdrsp_dicloc),
169 ntohs(pdu_in.xjdrsp_hitposn),
170 ntohs(pdu_in.xjdrsp_reslen),
171 pdu_in.xjdrsp_resstr,
172 ntohl(pdu_in.xjdrsp_checksum));
173 temp = ntohs(pdu_in.xjdrsp_type);
174 temp+= ntohs(pdu_in.xjdrsp_seq);
175 temp+= ntohl(pdu_in.xjdrsp_resindex);
176 temp+= ntohl(pdu_in.xjdrsp_dicloc);
177 temp+= ntohs(pdu_in.xjdrsp_hitposn);
178 temp+= ntohs(pdu_in.xjdrsp_reslen);
179 for (i = 0; i < strlen(pdu_in.xjdrsp_resstr); i++)
180 temp+= pdu_in.xjdrsp_resstr[i];
181 if (ntohl(pdu_in.xjdrsp_checksum) == temp)
182 {
183 chk_cnt = 0;
184 return (TRUE);
185 }
186 if (CVERBOSE) printf("Cal checksum: %d PDU checksum: %d\n",temp,ntohl(pdu_in.xjdrsp_checksum));
187 if (chk_cnt++ > 20)
188 {
189 printf("20 consecutive checksum failures: Try again? ");
190 scanf("%s",&yn);
191 printf("\n");
192 if((yn[0] | 0x20) == 'y')
193 {
194 chk_cnt = 0;
195 return(FALSE);
196 }
197 else
198 {
199 exit(1);
200 }
201 }
202 return (FALSE);
203 }
204
reqchecksum()205 void reqchecksum()
206 {
207 long temp;
208 int i;
209
210 temp = ntohs(pdu_out.xjdreq_type);
211 temp+= ntohs(pdu_out.xjdreq_seq);
212 temp+= ntohs(pdu_out.xjdreq_dicno);
213 temp+= ntohl(pdu_out.xjdreq_indexpos);
214 temp+= ntohs(pdu_out.xjdreq_schlen);
215 for (i = 0; i < strlen(pdu_out.xjdreq_schstr); i++) temp+= pdu_out.xjdreq_schstr[i];
216
217 pdu_out.xjdreq_checksum = htonl(temp);
218 }
219
xjdserver(int type,int dic_no,long index_posn,int sch_str_len,unsigned char * sch_str,int * sch_resp,long * res_index,int * hit_posn,int * res_len,unsigned char * res_str,long * dic_loc)220 void xjdserver (int type, int dic_no, long index_posn, int sch_str_len,
221 unsigned char *sch_str, int *sch_resp, long *res_index,
222 int *hit_posn, int *res_len, unsigned char *res_str,
223 long *dic_loc )
224 {
225 int i, ares, sendit;
226
227 gettimeofday((struct timeval *)&timeout,(struct timezone *)&tz);
228 timeofday_st = timeout.tv_sec;
229 pdu_out.xjdreq_type = htons(type);
230 pdu_out.xjdreq_seq = htons(++pduseq);
231 pdu_out.xjdreq_dicno = htons(dic_no);
232 pdu_out.xjdreq_indexpos = htonl(index_posn);
233 pdu_out.xjdreq_schlen = htons(sch_str_len);
234 strcpy(pdu_out.xjdreq_schstr,sch_str);
235 reqchecksum();
236 sendit = TRUE;
237 while (TRUE)
238 {
239 timeout.tv_sec = curr_timer;
240 timeout.tv_usec = 0;
241 if (sendit)
242 {
243 txno++;
244 (void) write (s, &pdu_out,sizeof(REQ_PDU));
245 if (CVERBOSE) printf("txno %d (seq: %d)\n",txno,pduseq);
246 }
247 if ((ares = select(nfds, &fildesc, (fd_set *)0, (fd_set *)0, (struct timeval *)&timeout) )< 0)
248 {
249 printf("Select error: %s\n", strerror(errno));
250 exit(1);
251 }
252 sendit = TRUE;
253 if (ares == 0)
254 {
255 if (CVERBOSE) printf("Timeout: %d secs (seq: %d)\n",curr_timer,pduseq);
256 FD_SET(s, &fildesc);
257 if (rep_count < TMAXREP)
258 {
259 rep_count++;
260 continue;
261 }
262 else
263 {
264 if (curr_timer >= TMAXVAL)
265 {
266 rep_count = 0;
267 printf("Cannot contact Server: %s Try again? ",host);
268 scanf("%s",&yn);
269 printf("\n");
270 if((yn[0] | 0x20) == 'y')
271 {
272 curr_timer = TINITVAL;
273 continue;
274 }
275 else
276 {
277 exit(1);
278 }
279 }
280 else
281 {
282 curr_timer*=2;
283 rep_count = 0;
284 continue;
285 }
286 }
287 }
288 if (CVERBOSE) printf("Something in!\n");
289 gettimeofday((struct timeval *)&timeout,(struct timezone *)&tz);
290 timeofday_en = timeout.tv_sec;
291 elapse = timeofday_en - timeofday_st;
292 if (elapse < 1) elapse = 1;
293 if (elapse > curr_timer)
294 {
295 curr_timer = elapse << 1;
296 }
297 else
298 {
299 if (curr_timer - elapse > 2) curr_timer = elapse+2;
300 }
301 if (recv(s, &pdu_in, sizeof(RSP_PDU), 0) < 0)
302 {
303 if (errno == 111)
304 {
305 printf("Cannot contact Server: %s Try again?\n",host);
306 scanf("%s",&yn);
307 if((yn[0] | 0x20) == 'y')
308 {
309 continue;
310 }
311 else
312 {
313 exit(1);
314 }
315 }
316 printf("UDP recv error: %d %s\n",errno,strerror(errno));
317 exit(1);
318 }
319 if (!respchecksum())
320 {
321 if (CVERBOSE) printf("PDU checksum error (seq: %d)\n",pduseq);
322 continue;
323 }
324 if (ntohs(pdu_in.xjdrsp_seq) != pduseq)
325 {
326 if (CVERBOSE) printf("PDU sequence error. Rec: %d Exp: %d\n",ntohs(pdu_in.xjdrsp_seq),pduseq);
327 sendit = FALSE;
328 continue;
329 }
330 if (CVERBOSE) printf("Valid PDU: %d %ld %d %d\n",ntohs(pdu_in.xjdrsp_type),
331 ntohl(pdu_in.xjdrsp_resindex),
332 ntohs(pdu_in.xjdrsp_hitposn),
333 ntohs(pdu_in.xjdrsp_reslen));
334 *sch_resp = ntohs(pdu_in.xjdrsp_type);
335 *res_index = ntohl(pdu_in.xjdrsp_resindex);
336 *hit_posn = ntohs(pdu_in.xjdrsp_hitposn);
337 *res_len = ntohs(pdu_in.xjdrsp_reslen);
338 *dic_loc = ntohl(pdu_in.xjdrsp_dicloc);
339 for (i = 0; i < *res_len; i++)
340 {
341
342 res_str[i] = pdu_in.xjdrsp_resstr[i];
343 res_str[i+1] = 0;
344 }
345 return;
346 }
347
348
349 }
350