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