struct hdr cli_recv(int fd, void *inbuff, size_t inbytes)
{
    ssize_t         n;
    struct iovec    iovrecv[2];
    struct rtt_info   rttinfo;


    msgrecv.msg_name = NULL;
    msgrecv.msg_namelen = 0;
    msgrecv.msg_iov = iovrecv;
    msgrecv.msg_iovlen = 2;
    iovrecv[0].iov_base = &recvhdr;
    iovrecv[0].iov_len = sizeof(struct hdr);
    iovrecv[1].iov_base = inbuff;
    iovrecv[1].iov_len = inbytes;

    rttinfo.rtt_rto = CLI_TIMEOUT; //8 sec time out

    if (rttinit == 0) {
        rtt_init(&rttinfo);     /* first time we're called */
        rttinit = 1;
        rtt_d_flag = 1;
    }

    Signal(SIGALRM, sig_alrm);
    rtt_newpack(&rttinfo);      /* initialize for this packet */

    alarm(rtt_start(&rttinfo)/1000); /* calc timeout value & start timer */

//#ifdef  RTT_DEBUG
    rtt_debug(&rttinfo);
//#endif

    if (sigsetjmp(jmpbuf, 1) != 0) {
            err_msg("cli_recv: no response from server, giving up");
            rttinit = 0;    /* reinit in case we're called again */
            errno = ETIMEDOUT;
            err_sys("[ERROR]: Timeout");
            return recvhdr;
    }

    n = Recvmsg(fd, &msgrecv, 0);
    if (n < sizeof(struct hdr)){
        err_sys("[ERROR]: Received packet incomplete");
    }

    printf("Length: %d\n", (int)n);
    //printf("BUFFER: %s\n", (char *)iovrecv[1].iov_base);
    printf("SEQ NUM: %u\n", recvhdr.seq);
    printf("IS FIN: %u\n", recvhdr.fin);
    alarm(0);           /* stop SIGALRM timer */
    return(recvhdr); /* return size of received datagram */
}
Beispiel #2
0
ssize_t
dg_send_recv(int fd, const void *outbuff, size_t outbytes,
			 void *inbuff, size_t inbytes,
			 const SA *destaddr, socklen_t destlen)
{
	ssize_t			n;
	struct iovec	iovsend[2], iovrecv[2];

	if (rttinit == 0) {
		rtt_init(&rttinfo);		/* first time we're called */
		rttinit = 1;
		rtt_d_flag = 1;
	}

	sendhdr.seq++;
	msgsend.msg_name = destaddr;
	msgsend.msg_namelen = destlen;
	msgsend.msg_iov = iovsend;
	msgsend.msg_iovlen = 2;
	iovsend[0].iov_base = &sendhdr;
	iovsend[0].iov_len = sizeof(struct hdr);
	iovsend[1].iov_base = outbuff;
	iovsend[1].iov_len = outbytes;

	msgrecv.msg_name = NULL;
	msgrecv.msg_namelen = 0;
	msgrecv.msg_iov = iovrecv;
	msgrecv.msg_iovlen = 2;
	iovrecv[0].iov_base = &recvhdr;
	iovrecv[0].iov_len = sizeof(struct hdr);
	iovrecv[1].iov_base = inbuff;
	iovrecv[1].iov_len = inbytes;
/* end dgsendrecv1 */

/* include dgsendrecv2 */
	if (signal(SIGALRM, sig_alrm) == SIG_ERR) {
		perror("signal error");
		exit(1);
	}
	rtt_newpack(&rttinfo);		/* initialize for this packet */

sendagain:
#ifdef	RTT_DEBUG
	fprintf(stderr, "send %4d: ", sendhdr.seq);
#endif
	sendhdr.ts = rtt_ts(&rttinfo);
	int nbytes = 0;	/* must first figure out what return value should be */
	int i;
	for (i = 0; i < msgsend.msg_iovlen; i++)
		nbytes += msgsend.msg_iov[i].iov_len;
	if (sendmsg(fd, &msgsend, 0) != nbytes) {
		perror("sendmsg error");
		exit(1);
	}

	alarm(rtt_start(&rttinfo));	/* calc timeout value & start timer */
#ifdef	RTT_DEBUG
	rtt_debug(&rttinfo);
#endif

	if (sigsetjmp(jmpbuf, 1) != 0) {
		if (rtt_timeout(&rttinfo) < 0) {
			fprintf(stderr, "dg_send_recv: no response from server, giving up\n");
			rttinit = 0;	/* reinit in case we're called again */
			errno = ETIMEDOUT;
			return(-1);
		}
#ifdef	RTT_DEBUG
		fprintf(stderr, "dg_send_recv: timeout, retransmitting\n");
#endif
		goto sendagain;
	}

	do {
		if ((n = recvmsg(fd, &msgrecv, 0)) < 0) {
			perror("recvmsg error");
			exit(1);
		}
#ifdef	RTT_DEBUG
		fprintf(stderr, "recv %4d\n", recvhdr.seq);
#endif
	} while (n < sizeof(struct hdr) || recvhdr.seq != sendhdr.seq);

	alarm(0);			/* stop SIGALRM timer */
		/* 4calculate & store new RTT estimator values */
	rtt_stop(&rttinfo, rtt_ts(&rttinfo) - recvhdr.ts);

	return(n - sizeof(struct hdr));	/* return size of received datagram */
}
Beispiel #3
0
static int su_serv_send_recv_act(su_serv_t *psvr, SA *destaddr, socklen_t destlen,
                                 const void *outbuff, int outbytes, void *inbuff, int inbytes, int retransmit)
{
    int             n;
    struct iovec    iovsend[2]= {{0}};
    struct msghdr   msgsend = {0};	    /* assumed init to 0 */
    suhdr_t *r, sendhdr = {0};          /* protocol header */
    int ret, waitsec;

    struct list *node = 0;
    frames_t *packet = 0;

    pthread_mutex_lock(&psvr->mutex);
    pthread_mutex_lock(&psvr->lock);

    if (retransmit == 0) {
        psvr->seq++;
        psvr->retransmission = 1;
    } else {
        if (psvr->retransmission == 0) {
            pthread_mutex_unlock(&psvr->mutex);
            pthread_mutex_unlock(&psvr->lock);
            errno = ETIMEDOUT;
            return -1;
        }
        psvr->retransmission --;
    }

    if (psvr->rttinit == 0) {
        rtt_init(&psvr->rttinfo, psvr->retry); /* first time we're called */
        psvr->rttinit = 1;
    }

    sendhdr.act  = SU_SYN;
    sendhdr.type = SU_RELIABLE;
    sendhdr.sid  = psvr->sid;
    sendhdr.seq  = psvr->seq;
    msgsend.msg_name = (void*)destaddr;
    msgsend.msg_namelen = destlen;
    msgsend.msg_iov = iovsend;
    msgsend.msg_iovlen = 2;

    iovsend[0].iov_base = (void*)&sendhdr;
    iovsend[0].iov_len = sizeof(suhdr_t);
    iovsend[1].iov_base = (void*)outbuff;
    iovsend[1].iov_len = outbytes;

    struct timespec abstime = {0};
    suhdr_t *precvhdr;

    rtt_newpack(&psvr->rttinfo);		/* initialize for this packet */
    psvr->ackwaitnum ++;

sendagain:
    sendhdr.ts = rtt_ts(&psvr->rttinfo);
    if (sendmsg(psvr->fd, &msgsend, 0) < 0) {
        ERR_RET("sendmsg error");
        goto error_ret;
    }

    waitsec = rtt_start(&psvr->rttinfo);	/* calc timeout value & start timer */
#ifdef	SU_DEBUG_RTT
    fprintf(stderr, ColorRed "send seq %4d: " ColorEnd, sendhdr.seq);
    rtt_debug(&psvr->rttinfo);
#endif

    /* set timed wait time-point */
    maketimeout_seconds(&abstime, waitsec);

#ifdef SU_DEBUG_TIMEVERBOSE
    struct timeval now;
    gettimeofday(&now, 0);
    log_msg( ColorBlue "pthread_cond_timedwait : %u.%u time expire" ColorEnd,
             abstime.tv_sec, abstime.tv_nsec);
    log_msg( ColorBlue "pthread_cond_timedwait : %d.%d now time" ColorEnd,
             now.tv_sec, now.tv_usec*1000);
#endif

timedwaitagain:
    ret = pthread_cond_timedwait(&psvr->ackcond, &psvr->lock, &abstime);
    if (ret == 0) {
#ifdef SU_DEBUG_TIMEVERBOSE
        struct timeval now;
        gettimeofday(&now, 0);
        log_msg(ColorBlue "pthread_cond_timedwait : %d.%d ack cond interrupt" ColorEnd,
                now.tv_sec, now.tv_usec*1000);
#endif
        node = psvr->ackrecvls.next;
        for (; node != &psvr->ackrecvls; node = node->next) {
            packet = container_of(node, frames_t, node);
            r = &packet->recvhdr;
            if (su_cmp_ack_SU_RELIABLE(&sendhdr, r)) {
                break;
            }
        }
        if ( node == &psvr->ackrecvls ) {
            /* Be careful of the lock, locked -> timedwait -> unlock */
#ifdef SU_DEBUG_LIST
            log_msg("serv %x no found seq %d ack, timed wait again", psvr, sendhdr.seq);
#endif
            goto timedwaitagain;
        }

        /* Find response packet node */
        list_remove(&packet->node);

        n = packet->len;
        precvhdr = &packet->recvhdr;

#if defined SU_DEBUG_PEER_RECV || defined SU_DEBUG_LIST
        log_msg("serv %x finded ack " ColorRed "%p" ColorEnd " seq %d datagram len %d",
                psvr, packet, r->seq, packet->len);
#endif

#ifdef	SU_DEBUG_RTT
        fprintf(stderr, ColorRed "recv seq %4d \n" ColorEnd, precvhdr->seq);
#endif
        // SU_RELIABLE received response, copy to user buffer
        memcpy(inbuff, packet->data, n > inbytes ? inbytes : n);

    } else if (ret == EINTR) {
        log_msg("pthread_cond_timedwait system EINTR");
        goto timedwaitagain;
    } else if (ret == ETIMEDOUT) {
#ifdef SU_DEBUG_TIMEVERBOSE
        struct timeval now;
        gettimeofday(&now, 0);
        log_msg(ColorBlue "pthread_cond_timedwait : %u.%u ETIMEOUT have expired" ColorEnd,
                now.tv_sec, now.tv_usec*1000);
#endif
        if (rtt_timeout(&psvr->rttinfo) < 0) {
#ifdef	SU_DEBUG_RTT
            err_msg(ColorYel "no response from server, giving up" ColorEnd);
#endif
            psvr->rttinit = 0;	/* reinit in case we're called again */
            errno = ETIMEDOUT;
            goto error_ret;
        }
#ifdef	SU_DEBUG_RTT
        err_msg(ColorRed "     seq %4d timeout, retransmitting %d" ColorEnd,
                sendhdr.seq, ++retransmit);
#endif
        goto sendagain;
    } else {
        errno = ret;
        ERR_RET(" su_serv_send_recv_act unknown error[%d]", ret);
        goto error_ret;
    }

    /* calculate & store new RTT estimator values */
    rtt_stop(&psvr->rttinfo, rtt_ts(&psvr->rttinfo) - precvhdr->ts);

    if (--psvr->ackwaitnum == 0) {
        su_serv_list_empty(psvr, &psvr->ackrecvls);
    }
    pthread_mutex_unlock(&psvr->mutex);
    pthread_mutex_unlock(&psvr->lock);

#ifdef SU_DEBUG_LIST
    log_msg("serv %x free node  " ColorRed "%p"ColorEnd" seq %d", psvr, packet, sendhdr.seq);
#endif

    free(packet);

    return(n);	/* return size of received datagram */

error_ret:
    if (--psvr->ackwaitnum == 0) {
        su_serv_list_empty(psvr, &psvr->ackrecvls);
    }
    pthread_mutex_unlock(&psvr->mutex);
    pthread_mutex_unlock(&psvr->lock);
    return(-1);
}
ssize_t 
dg_send_recv(int fd, const void *outbuff, size_t outbytes, 
	     void *inbuff, size_t inbytes, 
	     const SA *destaddr, socklen_t destlen) 
{ 
	ssize_t n; 
	struct iovec iovsend[2], iovrecv[2];
	fd_set rset;
	int nsel, maxfdp1;
	struct timeval tv;
 
	if (rttinit == 0) { 
		rtt_init(&rttinfo); /* first time we're called */ 
		rttinit = 1; 
		rtt_d_flag = 1; 
	} 
 
	sendhdr.seq++; 
	msgsend.msg_name = destaddr; 
	msgsend.msg_namelen = destlen; 
	msgsend.msg_iov = iovsend; 
	msgsend.msg_iovlen = 2; 
	iovsend[0].iov_base = &sendhdr; 
	iovsend[0].iov_len = sizeof(struct hdr); 
	iovsend[1].iov_base = outbuff; 
	iovsend[1].iov_len = outbytes; 
 
	msgrecv.msg_name = NULL; 
	msgrecv.msg_namelen = 0; 
	msgrecv.msg_iov = iovrecv; 
	msgrecv.msg_iovlen = 2; 
	iovrecv[0].iov_base = &recvhdr; 
	iovrecv[0].iov_len = sizeof(struct hdr); 
	iovrecv[1].iov_base = inbuff; 
	iovrecv[1].iov_len = inbytes; 

	rtt_newpack(&rttinfo); /* initialize for this packet */ 
 
sendagain: 
#ifdef RTT_DEBUG 
	fprintf(stderr, "send %4d: ", sendhdr.seq); 
#endif 
	sendhdr.ts = rtt_ts(&rttinfo); 
	Sendmsg(fd, &msgsend, 0); 
 
	alarm(rtt_start(&rttinfo)); /* calc timeout value & start timer */ 
#ifdef RTT_DEBUG 
	rtt_debug(&rttinfo); 
#endif 

	tv.tv_sec = rtt_start(&rttinfo);
	tv.tv_usec = 0;
	maxfdp1 = fd + 1;	

again:
	FD_ZERO(&rset);
	FD_SET(fd, &rset);
	nsel = select(maxfdp1, &rset, NULL, NULL, &tv);
	if ((nsel == -1) || (errno == EINTR))
		goto again;
	else if (nsel == -1)
		err_msg("select error");
	else if (nsel == 0) {
		if (rtt_timeout(&rttinfo) < 0) { 
			err_msg("dg_send_recv: no response from server, giving up"); 
			rttinit = 0; /* reinit in case we're called again */ 
			errno = ETIMEDOUT; 
			return(-1); 
		} 
#ifdef RTT_DEBUG 
		err_msg("dg_send_recv: timeout, retransmitting"); 
#endif 
		goto sendagain; 
	}
	if (FD_ISSET(fd, &rset)) {
		do { 
			n = Recvmsg(fd, &msgrecv, 0); 
#ifdef RTT_DEBUG 
			fprintf(stderr, "recv %4d\n", recvhdr.seq); 
#endif 
		} while (n < sizeof(struct hdr) || recvhdr.seq != sendhdr.seq); 
	}

	/* 4calculate & store new RTT estimator values */ 
	rtt_stop(&rttinfo, rtt_ts(&rttinfo) - recvhdr.ts); 
 
	return(n - sizeof(struct hdr)); /* return size of received datagram */ 
}