dg_send_recv.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /* include dgsendrecv1 */
  2. #include "unprtt.h"
  3. #include <setjmp.h>
  4. #define RTT_DEBUG
  5. static struct rtt_info rttinfo;
  6. static int rttinit = 0;
  7. static struct msghdr msgsend, msgrecv; /* assumed init to 0 */
  8. static struct hdr {
  9. uint32_t seq; /* sequence # */
  10. uint32_t ts; /* timestamp when sent */
  11. } sendhdr, recvhdr;
  12. static void sig_alrm(int signo);
  13. static sigjmp_buf jmpbuf;
  14. ssize_t
  15. dg_send_recv(int fd, const void *outbuff, size_t outbytes,
  16. void *inbuff, size_t inbytes,
  17. const SA *destaddr, socklen_t destlen)
  18. {
  19. ssize_t n;
  20. struct iovec iovsend[2], iovrecv[2];
  21. if (rttinit == 0) {
  22. rtt_init(&rttinfo); /* first time we're called */
  23. rttinit = 1;
  24. rtt_d_flag = 1;
  25. }
  26. sendhdr.seq++;
  27. msgsend.msg_name = destaddr;
  28. msgsend.msg_namelen = destlen;
  29. msgsend.msg_iov = iovsend;
  30. msgsend.msg_iovlen = 2;
  31. iovsend[0].iov_base = &sendhdr;
  32. iovsend[0].iov_len = sizeof(struct hdr);
  33. iovsend[1].iov_base = outbuff;
  34. iovsend[1].iov_len = outbytes;
  35. msgrecv.msg_name = NULL;
  36. msgrecv.msg_namelen = 0;
  37. msgrecv.msg_iov = iovrecv;
  38. msgrecv.msg_iovlen = 2;
  39. iovrecv[0].iov_base = &recvhdr;
  40. iovrecv[0].iov_len = sizeof(struct hdr);
  41. iovrecv[1].iov_base = inbuff;
  42. iovrecv[1].iov_len = inbytes;
  43. /* end dgsendrecv1 */
  44. /* include dgsendrecv2 */
  45. Signal(SIGALRM, sig_alrm);
  46. rtt_newpack(&rttinfo); /* initialize for this packet */
  47. sendagain:
  48. #ifdef RTT_DEBUG
  49. fprintf(stderr, "send %4d: ", sendhdr.seq);
  50. #endif
  51. sendhdr.ts = rtt_ts(&rttinfo);
  52. Sendmsg(fd, &msgsend, 0);
  53. alarm(rtt_start(&rttinfo)); /* calc timeout value & start timer */
  54. #ifdef RTT_DEBUG
  55. rtt_debug(&rttinfo);
  56. #endif
  57. if (sigsetjmp(jmpbuf, 1) != 0) {
  58. if (rtt_timeout(&rttinfo) < 0) {
  59. err_msg("dg_send_recv: no response from server, giving up");
  60. rttinit = 0; /* reinit in case we're called again */
  61. errno = ETIMEDOUT;
  62. return(-1);
  63. }
  64. #ifdef RTT_DEBUG
  65. err_msg("dg_send_recv: timeout, retransmitting");
  66. #endif
  67. goto sendagain;
  68. }
  69. do {
  70. n = Recvmsg(fd, &msgrecv, 0);
  71. #ifdef RTT_DEBUG
  72. fprintf(stderr, "recv %4d\n", recvhdr.seq);
  73. #endif
  74. } while (n < sizeof(struct hdr) || recvhdr.seq != sendhdr.seq);
  75. alarm(0); /* stop SIGALRM timer */
  76. /* 4calculate & store new RTT estimator values */
  77. rtt_stop(&rttinfo, rtt_ts(&rttinfo) - recvhdr.ts);
  78. return(n - sizeof(struct hdr)); /* return size of received datagram */
  79. }
  80. static void
  81. sig_alrm(int signo)
  82. {
  83. siglongjmp(jmpbuf, 1);
  84. }
  85. /* end dgsendrecv2 */
  86. ssize_t
  87. Dg_send_recv(int fd, const void *outbuff, size_t outbytes,
  88. void *inbuff, size_t inbytes,
  89. const SA *destaddr, socklen_t destlen)
  90. {
  91. ssize_t n;
  92. n = dg_send_recv(fd, outbuff, outbytes, inbuff, inbytes,
  93. destaddr, destlen);
  94. if (n < 0)
  95. err_quit("dg_send_recv error");
  96. return(n);
  97. }