File: lib.c

package info (click to toggle)
fsp 2.71-8hamm10
  • links: PTS
  • area: main
  • in suites: hamm
  • size: 988 kB
  • ctags: 1,287
  • sloc: ansic: 7,715; makefile: 363; sh: 118
file content (154 lines) | stat: -rw-r--r-- 4,561 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
    /*********************************************************************\
    *  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 int, 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;
  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 + (busy_delay >> 1);
	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 < 5*60*1000) idle_delay = idle_delay << 1;
	w_delay = idle_delay;
	if(client_trace) write(2,"I",1);
	break;
    }
      
    if(sendto(myfd,&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);
	}
	      
	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);
}