/protocols/udp/udp_connection.cpp

https://github.com/nanomo/network-traffic-generator · C++ · 207 lines · 188 code · 19 blank · 0 comment · 33 complexity · 4fa4b1bb7e194e054c7dcfae4bb4eb41 MD5 · raw file

  1. #include "../../config.h"
  2. #ifdef HAVE_SYS_TYPES_H
  3. #include <sys/types.h>
  4. #endif
  5. #ifdef HAVE_SYS_SOCKET_H
  6. #include <sys/socket.h>
  7. #endif
  8. #ifdef HAVE_NETDB_H
  9. #include <netdb.h>
  10. #endif
  11. #ifdef HAVE_ARPA_INET_H
  12. #include <arpa/inet.h>
  13. #endif
  14. #ifdef HAVE_SYS_POLL_H
  15. #include <sys/poll.h>
  16. #endif
  17. #ifdef HAVE_MEMORY_H
  18. #include <memory.h>
  19. #endif
  20. #include "udp_connection.h"
  21. #include "../loadprotocol.h"
  22. #include "../../os/os.h"
  23. udp_connection::udp_connection(char *dest_addr, unsigned dest_port, char *local_addr, unsigned local_port, void *other)
  24. {
  25. installed=0;
  26. sock=-1;
  27. dont_close=0;
  28. readd=0;
  29. writed=0;
  30. memset( &local_address, 0, sizeof(local_address) );
  31. struct protoent *pr;
  32. int result;
  33. pr=getprotobyname( "udp" );
  34. if (!pr) return;
  35. addr.sin_family=AF_INET;
  36. addr.sin_port=htons( dest_port );
  37. result=TranslateInetString( dest_addr, &addr.sin_addr, sizeof(addr.sin_addr) );
  38. if (result<0) return;
  39. sock=socket( PF_INET, SOCK_DGRAM, pr->p_proto );
  40. if (sock<0) return;
  41. if (local_addr || local_port)
  42. { // we have to bind!
  43. local_address.sin_family=AF_INET;
  44. local_address.sin_port=htons( local_port );
  45. if (local_addr)
  46. {
  47. result=TranslateInetString( local_addr, &local_address.sin_addr, sizeof(local_address.sin_addr) );
  48. if (result<0) return;
  49. }
  50. if (bind( sock, (struct sockaddr *)&local_address, sizeof(local_address) )<0) return;
  51. }
  52. #if !defined(__WIN32__)
  53. if (connect( sock, (const sockaddr *)&addr, sizeof(addr) )<0) return;
  54. #endif
  55. installed=1;
  56. }
  57. udp_connection::udp_connection( int listen_sock, void *other )
  58. {
  59. installed=0;
  60. sock=-1;
  61. dont_close=1;
  62. readd=0;
  63. writed=0;
  64. sock=listen_sock;
  65. if (sock<0) return;
  66. installed=1;
  67. }
  68. udp_connection::~udp_connection()
  69. {
  70. if (sock>=0 && !dont_close)
  71. {
  72. shutdown( sock, SHUT_RDWR );
  73. close( sock );
  74. sock=-1;
  75. }
  76. }
  77. int udp_connection::write( char *data, int len )
  78. {
  79. if (!isOk()) return( -1 );
  80. if (len<=0 || !data) return( 0 );
  81. int result;
  82. result=::sendto( sock, data, len, 0, (const struct sockaddr *)&addr, sizeof(addr) );
  83. if (result>0) writed+=result;
  84. return( result );
  85. }
  86. int udp_connection::read( char *data, int len, char *remote_addr, int remote_len, int flags )
  87. {
  88. if (!isOk()) return( -1 );
  89. if (len<=0 || !data) return( 0 );
  90. int result, rflag;
  91. socklen_t slen;
  92. rflag=PROTOCOL_NONE;
  93. if (flags&PROTOCOL_PEEK) rflag|=MSG_PEEK;
  94. #if defined(__WIN32__)
  95. data[0]=0;
  96. #endif
  97. slen=sizeof( addr );
  98. result=::recvfrom( sock, data, len, rflag, (struct sockaddr *)&addr, &slen );
  99. #if defined(__WIN32__)
  100. if (flags&PROTOCOL_PEEK)
  101. { // Windows can not do peek properly
  102. if (data[0]!=0)
  103. result=len;
  104. }
  105. #endif
  106. if (result>0) readd+=result;
  107. if (remote_addr && remote_len>0)
  108. {
  109. #if defined(__WIN32__)
  110. strncpy( remote_addr, inet_ntoa( addr.sin_addr ), remote_len );
  111. #else
  112. inet_ntop( AF_INET, &(addr.sin_addr), remote_addr, remote_len );
  113. #endif
  114. }
  115. return( result );
  116. }
  117. void udp_connection::transfered( LONGLONG *readr, LONGLONG *writew )
  118. {
  119. if (readr) *readr=readd;
  120. if (writew) *writew=writed;
  121. }
  122. int udp_connection::ready( int why )
  123. {
  124. if (!isOk()) return( -1 );
  125. #if defined(__WIN32__)
  126. fd_set setr, setw;
  127. int result;
  128. struct timeval delay;
  129. FD_ZERO( &setr );
  130. FD_ZERO( &setw );
  131. switch (why)
  132. {
  133. case 1:
  134. FD_SET( sock, &setr );
  135. break;
  136. case 2:
  137. FD_SET( sock, &setw );
  138. break;
  139. default:
  140. FD_SET( sock, &setr );
  141. FD_SET( sock, &setw );
  142. break;
  143. };
  144. delay.tv_sec=0;
  145. delay.tv_usec=0;
  146. result=select( 1, &setr, &setw, NULL, &delay );
  147. switch (result)
  148. {
  149. case SOCKET_ERROR: // bad
  150. return( -1 );
  151. case 0: // timeout
  152. return( 0 );
  153. case 1: // ready
  154. return( 1 );
  155. };
  156. #else
  157. struct pollfd pfd;
  158. int result;
  159. pfd.fd=sock;
  160. pfd.revents=0;
  161. switch (why)
  162. {
  163. case 1:
  164. pfd.events=POLLIN;
  165. break;
  166. case 2:
  167. pfd.events=POLLOUT;
  168. break;
  169. default:
  170. pfd.events=POLLIN|POLLOUT;
  171. };
  172. result=poll( &pfd, 1, 1 ); // 1ms wait
  173. switch (result)
  174. {
  175. case -1: // error
  176. return( -1 );
  177. case 0: // nothing to report
  178. return( 0 );
  179. case 1: // Something to report
  180. return( 1 );
  181. }
  182. #endif
  183. }
  184. int udp_connection::operator==( udp_connection &other )
  185. {
  186. if (sock==other.sock) return( 1 );
  187. return( 0 );
  188. }