File: lib.c

package info (click to toggle)
fsp 2.81.b3-2
  • links: PTS
  • area: main
  • in suites: potato
  • size: 1,072 kB
  • ctags: 1,264
  • sloc: ansic: 7,764; makefile: 357; sh: 312
file content (164 lines) | stat: -rw-r--r-- 4,697 bytes parent folder | download | duplicates (2)
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
    /*********************************************************************\
    *  Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu)   *
    *                                                                     *
    *  You may copy or modify this file in any manner you wish, provided  *
    *  that this notice is always included, and that you hold the author  *
    *  harmless for any loss or damage resulting from the installation or *
    *  use of this software.                                              *
    \*********************************************************************/

#include "tweak.h"
#include "client_def.h"
#include "c_extern.h"
#include "co_extern.h"

extern int errno;

static int myfd;
static struct sockaddr_in server_addr;
static unsigned short myseq = 0;
static unsigned short key;

int client_trace = 0;
int client_intr_state = 0;
unsigned long target_delay = MIN_DELAY;	/* expected max delay	 */
unsigned long busy_delay = MIN_DELAY;	/* busy retransmit timer */
unsigned long idle_delay = MIN_DELAY;	/* idle retransmit timer */
unsigned long udp_sent_time;

UBUF *client_interact PROTO6(unsigned char, cmd, unsigned long, pos,
			     unsigned int, l1, unsigned char *, p1,
			     unsigned int, l2, unsigned char *, p2)
{
  struct sockaddr_in from;
  UBUF sbuf;
  static UBUF rbuf;
  unsigned char *s, *t, *d, seq0, seq1;
  unsigned u, n, sum, mask, mlen, rlen;
  int retval, bytes, retry_send, retry_recv;
  unsigned long w_delay;
  
  sbuf.cmd = cmd;

#ifdef DEBUG
  printf("sbuf.cmd = %u\n",sbuf.cmd);
#endif

  BB_WRITE2(sbuf.bb_len,l1);
  BB_WRITE4(sbuf.bb_pos,pos);
  
  client_intr_state = 1;
  
  for(u = l1, d = (unsigned char *) sbuf.buf; u--; *d++ = *p1++);
  for(u = l2; u--; *d++ = *p2++);
  mlen = d - (unsigned char *) &sbuf;
  
  key = client_get_key();
  
  for(retry_send = 0; ; retry_send++) {
    BB_WRITE2(sbuf.bb_key,key);
    sbuf.bb_seq[0] = seq0 = (myseq >> 8) & 0xff;
    sbuf.bb_seq[1] = seq1 = (myseq & 0xfc) | (retry_send & 0x0003);
    sbuf.sum = 0;
    
    for(t = (unsigned char *) &sbuf, sum = n = mlen; n--; sum += *t++);
    sbuf.sum = sum + (sum >> 8);
      
    switch(retry_send) {	/* adaptive retry delay adjustments */
      case  0:
        busy_delay = (target_delay+(busy_delay<<3)-busy_delay)>>3;
	w_delay = busy_delay;
	break;
      case  1:
	busy_delay = busy_delay * 3 / 2;
	w_delay = busy_delay;
	if(client_trace) write(2,"R",1); break;
	  
      default:
#ifdef CLIENT_TIMEOUT
	if (!pos && retry_send >= env_timeout ) {
	  fprintf(stderr, "\rRemote server not responding.\n");
	  exit(1);
	}
#endif
	if(idle_delay < 3*60*1000) idle_delay = idle_delay * 3 / 2;
	w_delay = idle_delay;
	if(client_trace) write(2,"I",1);
	break;
    }
      
    if(sendto(myfd,(const char*)&sbuf,mlen,0,(struct sockaddr *)&server_addr,
	      sizeof(server_addr)) == -1) {
      perror("sendto");
      exit(1);
    }
    udp_sent_time = time((time_t *) 0);
    mask = 1 << myfd;
      
    for(retry_recv = 0; ; retry_recv++) {
      if(retry_recv && client_trace) write(2,"E",1);
      retval = _x_select(&mask, w_delay);
      if((retval == -1) && (errno == EINTR)) continue;
      if(retval == 1) { /* an incoming message is waiting */
	bytes = sizeof(from);
	if((bytes = recvfrom(myfd,(char*)&rbuf,sizeof(rbuf),0,
			     (struct sockaddr *)&from, &bytes)) < UBUF_HSIZE)
	  continue;
	      
	s = (unsigned char *) &rbuf;
	d = s + bytes;
	u = rbuf.sum; rbuf.sum = 0;
	for(t = s, sum = 0; t < d; sum += *t++);
	sum = (sum + (sum >> 8)) & 0xff;
	if(sum != u) continue;  /* wrong check sum */
	      
	rlen = BB_READ2(rbuf.bb_len);
	      
	if( (rbuf.bb_seq[0] ^ seq0) ||
	   ((rbuf.bb_seq[1] ^ seq1)&0xfc)) continue;  /* wrong seq # */
	if((int) (rlen+UBUF_HSIZE)  > bytes) continue;  /* truncated.  */
	      
	myseq = (myseq + 0x0004) & 0xfffc;  /* seq for next request */
	key = BB_READ2(rbuf.bb_key); /* key for next request */
	      
	client_put_key(key);
	      
	if(client_intr_state == 2) {
	  if(!key_persists) client_done();
	  exit(1);
	}

#ifdef DEBUG
  printf("rbuf.cmd = %u\n",rbuf.cmd);
#endif
      
	return(&rbuf);
	
      } else break;   /* go back to re-transmit buffer again */
    }
  }
}

void init_client PROTO3(char *, host, int, port, int, myport)
{
  busy_delay = idle_delay = target_delay;
  
  if((myfd = _x_udp(&myport)) == -1) {
    perror("socket open");
    exit(1);
  }
  
  if(_x_adr(host,port,&server_addr) == -1) {
    perror("server addr");
    exit(1);
  } 
  
  client_init_key(server_addr.sin_addr.s_addr,port,getpid());
}

int client_done PROTO0((void))
{
  (void) client_interact(CC_BYE, 0L, 0, (unsigned char *)NULLP, 0,
			 (unsigned char *)NULLP);
  return(0);
}