PageRenderTime 45ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/REL-0-6-2/FreeSpeech/data-flow/src/SocketStream.cc

#
C++ | 557 lines | 328 code | 155 blank | 74 comment | 77 complexity | 6c090f43bebf14d5ae8eaf63d4602a31 MD5 | raw file
Possible License(s): LGPL-2.0, GPL-2.0, LGPL-2.1
  1. #include "SocketStream.h"
  2. #include "BaseException.h"
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include <sys/socket.h>
  7. #include <netinet/in.h>
  8. #include <arpa/inet.h>
  9. #include <netdb.h>
  10. #include <fcntl.h>
  11. #include <errno.h>
  12. const int network_socket::BROADCAST_TYPE = 0;
  13. const int network_socket::TCP_STREAM_TYPE = 1;
  14. #define OVERFLOW_IDENT_STRLEN 8
  15. #define OVERFLOW_IDENT "OVERFLOW"
  16. #define OVERFLOW_BROADCAST_IP "255.255.255.255"
  17. network_socket::network_socket(int type, int port)
  18. : m_read_socket(0)
  19. , m_listen_socket(0)
  20. , m_write_socket(0), m_port(port), m_type(type) {
  21. switch (m_type) {
  22. case BROADCAST_TYPE:
  23. init_broadcast();
  24. break;
  25. case TCP_STREAM_TYPE:
  26. break;
  27. default:
  28. throw new GeneralException("Unknown packet type",__FILE__,__LINE__);
  29. break;
  30. }
  31. }
  32. network_socket::~network_socket() {
  33. //shutting down communication
  34. shutdown();
  35. }
  36. void network_socket::printOn (ostream &out) const {
  37. out<<"network_socket"<<endl;
  38. out<<"Type : "<<m_type<<endl;
  39. out<<"Port : "<<m_port<<endl;
  40. }
  41. void network_socket::init_broadcast() {
  42. printf("Broadcast device initialising...");
  43. // Set up the write socket (datagram type)
  44. //
  45. m_write_socket = socket(AF_INET, SOCK_DGRAM, 0);
  46. if (m_write_socket == -1) {
  47. perror(__PRETTY_FUNCTION__);
  48. throw new GeneralException("Unable to create write_socket",__FILE__,__LINE__);
  49. }
  50. //initialising write structure
  51. memset(&m_write_addr, 0, sizeof(m_write_addr));
  52. m_write_addr.sin_family = AF_INET;
  53. m_write_addr.sin_addr.s_addr = inet_addr(OVERFLOW_BROADCAST_IP);
  54. m_write_addr.sin_port = htons(m_port);
  55. // Set write socket options to allow broadcasting
  56. //
  57. u_int broadcast = 1;
  58. if (setsockopt(m_write_socket, SOL_SOCKET, SO_BROADCAST,(const char*)&broadcast, sizeof(broadcast)) < 0) {
  59. perror(__PRETTY_FUNCTION__);
  60. throw new GeneralException("Unable to allow broadcasting for write socket",__FILE__,__LINE__);
  61. }
  62. // Set up the read socket
  63. //
  64. m_read_socket = socket(PF_INET, SOCK_DGRAM, 0);
  65. if (m_read_socket == -1) {
  66. perror(__PRETTY_FUNCTION__);
  67. throw new GeneralException("Unable to create read_socket",__FILE__,__LINE__);
  68. }
  69. // Set socket options to allow sharing of port
  70. //
  71. u_int share = 1;
  72. if (setsockopt(m_read_socket, SOL_SOCKET, SO_REUSEADDR,(const char*)&share, sizeof(share)) < 0) {
  73. perror(__PRETTY_FUNCTION__);
  74. throw new GeneralException("Unable to share port for read_socket",__FILE__,__LINE__);
  75. }
  76. // Bind socket to port (any address)
  77. //
  78. memset(&m_read_addr, 0, sizeof(m_read_addr));
  79. m_read_addr.sin_family = AF_INET;
  80. m_read_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  81. m_read_addr.sin_port = htons(m_port);
  82. if (bind(m_read_socket, (sockaddr*) &m_read_addr, sizeof(m_read_addr)) < 0) {
  83. perror(__PRETTY_FUNCTION__);
  84. throw new GeneralException("Unable to bind read_socket",__FILE__,__LINE__);
  85. }
  86. // Set socket to non-blocking
  87. //
  88. if (fcntl(m_read_socket, F_SETFL, O_NONBLOCK) < 0) {
  89. perror(__PRETTY_FUNCTION__);
  90. throw new GeneralException("Unable set read_socket non-blocking",__FILE__,__LINE__);
  91. }
  92. //non blocking connexion
  93. m_blocking = false;
  94. printf("done\n");
  95. }
  96. void network_socket::shutdown() {
  97. printf("Shuting down...");
  98. // Close sockets
  99. //
  100. if (m_write_socket == m_read_socket) {
  101. close(m_write_socket);
  102. }
  103. else {
  104. close(m_write_socket);
  105. close(m_read_socket);
  106. }
  107. if (m_listen_socket) {
  108. close(m_listen_socket);
  109. }
  110. printf("done\n");
  111. }
  112. ///////////////////////////////////////////////////////////////////////////
  113. // Send a packet
  114. //
  115. size_t network_socket::send_packet(unsigned char *packet, size_t size) {
  116. unsigned int flags = 0;
  117. switch (m_type) {
  118. case BROADCAST_TYPE:
  119. if (sendto(m_write_socket, (const char*)packet, size,
  120. 0, (sockaddr*) &m_write_addr, sizeof(m_write_addr)) < 0) {
  121. perror(__PRETTY_FUNCTION__);
  122. throw new GeneralException("Unable to send packet",__FILE__,__LINE__);
  123. return 0;
  124. }
  125. break;
  126. case TCP_STREAM_TYPE:
  127. if (send(m_write_socket, (const char*)packet, size,flags) < 0) {
  128. perror(__PRETTY_FUNCTION__);
  129. throw new GeneralException("Unable to send packet",__FILE__,__LINE__);
  130. return 0;
  131. }
  132. break;
  133. default:
  134. throw new GeneralException("Unknown packet type",__FILE__,__LINE__);
  135. break;
  136. }
  137. return size;
  138. }
  139. ///////////////////////////////////////////////////////////////////////////
  140. // Receive a packet
  141. //
  142. size_t network_socket::recv_packet(unsigned char *packet, size_t size) {
  143. size_t packet_len = 0;
  144. unsigned int flags = 0;
  145. size_t addr_len = sizeof(m_read_addr);
  146. switch (m_type) {
  147. case BROADCAST_TYPE:
  148. packet_len = recvfrom(m_read_socket, (char*)packet, size, 0, (sockaddr*) &m_read_addr, &addr_len);
  149. if ((int) packet_len < 0) {
  150. if (errno == EAGAIN) {
  151. return 0;
  152. }
  153. else {
  154. perror(__PRETTY_FUNCTION__);
  155. throw new GeneralException("Unable to recv packet",__FILE__,__LINE__);
  156. return 0;
  157. }
  158. }
  159. break;
  160. case TCP_STREAM_TYPE:
  161. packet_len = recv(m_read_socket,packet,size,flags);
  162. if ((int) packet_len < 0) {
  163. if (errno == EAGAIN) {
  164. return 0;
  165. }
  166. else {
  167. perror(__PRETTY_FUNCTION__);
  168. throw new GeneralException("Unable to recv packet",__FILE__,__LINE__);
  169. return 0;
  170. }
  171. }
  172. break;
  173. default:
  174. throw new GeneralException("Unknown packet type",__FILE__,__LINE__);
  175. break;
  176. }
  177. //printf("read packet len = %d \n", (int) packet_len);
  178. return packet_len;
  179. }
  180. void network_socket::init_tcp_stream(bool blocking) {
  181. struct sockaddr_in serverp;
  182. int address_size;// size of server address struct
  183. struct hostent* entp;
  184. char host[256];
  185. int flags;// temp for old socket access flags
  186. int one = 1;
  187. char* first_dot;
  188. m_blocking = blocking;
  189. address_size = sizeof(serverp);
  190. if(gethostname(host,256) == -1) {
  191. throw new GeneralException("network_socket::init_tcp_stream : couldn't get hostname.",__FILE__,__LINE__);
  192. }
  193. /* now, strip down to just the hostname */
  194. if((first_dot = strchr(host,'.'))) {
  195. *first_dot = '\0';
  196. }
  197. cerr<<"current host : "<<host<<endl;
  198. if((entp = gethostbyname(host)) == NULL) {
  199. cerr<<"Did not find host : "<<host<<endl;
  200. throw new GeneralException("network_socket::init_tcp_stream : host unknown.",__FILE__,__LINE__);
  201. }
  202. memcpy(&(serverp.sin_addr), entp->h_addr_list[0], entp->h_length);
  203. serverp.sin_port = htons(m_port);
  204. /*
  205. * Create the INET socket.
  206. *
  207. */
  208. if((m_listen_socket = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
  209. perror("network_socket::init_tcp_stream : call to socket() failed; socket not created.");
  210. throw new GeneralException("network_socket::init_tcp_stream : socket not created.",__FILE__,__LINE__);
  211. }
  212. /*
  213. * let's say that our process should get the SIGIO's when it's
  214. * readable
  215. */
  216. if(fcntl(m_listen_socket, F_SETOWN, getpid()) == -1) {
  217. perror("network_socket::init_tcp_stream : call to fcntl() failed while setting socket "
  218. "pid ownership; socket not created.");
  219. shutdown();
  220. throw new GeneralException("network_socket::init_tcp_stream : could not change ownership of the socket."
  221. ,__FILE__,__LINE__);
  222. }
  223. /*
  224. * get the current access flags
  225. */
  226. if((flags = fcntl(m_listen_socket, F_GETFL)) == -1) {
  227. perror("network_socket::init_tcp_stream : call to fcntl failed while getting socket "
  228. "access flags; socket not created.");
  229. shutdown();
  230. throw new GeneralException("network_socket::init_tcp_stream : could not get flags of the socket."
  231. ,__FILE__,__LINE__);
  232. }
  233. if(!blocking) {
  234. /*
  235. * OR the current flags with
  236. * O_NONBLOCK (so we won't block), and write them back
  237. */
  238. if(fcntl(m_listen_socket, F_SETFL, flags | O_NONBLOCK ) == -1) {
  239. perror("network_socket::init_tcp_stream : call to :fcntl() failed while setting socket "
  240. "access flags; socket not created.");
  241. shutdown();
  242. throw new GeneralException("network_socket::init_tcp_stream : could not set flags (O_NONBLOCK) of the socket."
  243. ,__FILE__,__LINE__);
  244. }
  245. }//non blocking
  246. /* make sure we can reuse the port soon after */
  247. if(setsockopt(m_listen_socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&one, sizeof(one))) {
  248. perror("network_socket::init_tcp_stream : setsockopt(2) failed");
  249. throw new GeneralException("network_socket::init_tcp_stream : setsocktopt failed."
  250. ,__FILE__,__LINE__);
  251. }
  252. /*
  253. * Bind it to the port indicated
  254. * INADDR_ANY indicates that any network interface (IP address)
  255. * for the local host may be used (presumably the OS will choose the
  256. * right * one).
  257. *
  258. * Specifying sin_port = 0 would allow the system to choose the port.
  259. */
  260. serverp.sin_family = PF_INET;
  261. serverp.sin_addr.s_addr = INADDR_ANY;
  262. if(bind(m_listen_socket, (struct sockaddr*) &serverp, sizeof(serverp)) == -1) {
  263. perror ("network_socket::init_tcp_stream : bind() failed; socket not created.");
  264. shutdown();
  265. throw new GeneralException("network_socket::init_tcp_stream : bind failed."
  266. ,__FILE__,__LINE__);
  267. }
  268. cerr<<"init_tcp_stream done!"<<endl;
  269. }
  270. void network_socket::socket_listen(int backlog, bool blocking) {
  271. init_tcp_stream(blocking);
  272. cerr<<"listening"<<endl;
  273. if(listen(m_listen_socket,backlog)) {
  274. perror("network_socket::init_tcp_stream : listen(2) failed:");
  275. shutdown();
  276. throw new GeneralException("network_socket::init_tcp_stream : listen failed."
  277. ,__FILE__,__LINE__);
  278. }
  279. }
  280. void network_socket::socket_accept() {
  281. if (m_blocking) {
  282. cerr<<"accept (blocking)"<<endl;
  283. }
  284. else {
  285. cerr<<"accept (non-blocking)"<<endl;
  286. }
  287. //int accept(int s, struct sockaddr *addr, int *addrlen);
  288. socklen_t length;
  289. if((m_read_socket = accept(m_listen_socket,(struct sockaddr *)NULL, &length)) == -1) {
  290. perror("network_socket::server_accept error when calling accept()");
  291. shutdown();
  292. throw new GeneralException("network_socket::server_accept error when calling accept()",__FILE__,__LINE__);
  293. }
  294. //write & read sockets are the same
  295. m_write_socket = m_read_socket;
  296. //set the socket non blocking?
  297. //sending Overflow identification banner
  298. cerr<<"send banner"<<endl;
  299. unsigned char banner[] = {'O','V','E','R','F','L','O','W'};
  300. send_packet(&banner[0],OVERFLOW_IDENT_STRLEN);
  301. cerr<<"accept done!"<<endl;
  302. }
  303. void network_socket::socket_connect(const char *host) {
  304. struct sockaddr_in server;
  305. struct hostent* entp;
  306. int sock;
  307. unsigned char banner[OVERFLOW_IDENT_STRLEN];
  308. int numread;
  309. /* fill in server structure */
  310. server.sin_family = PF_INET;
  311. /*
  312. * this is okay to do, because gethostbyname(3) does no lookup if the
  313. * 'host' * arg is already an IP addr
  314. */
  315. if((entp = gethostbyname(host)) == NULL) {
  316. char message[256];
  317. sprintf(message, "player_connect() \"%s\" is an unknown host", host);
  318. throw new GeneralException(message,__FILE__,__LINE__);
  319. }
  320. memcpy(&server.sin_addr, entp->h_addr_list[0], entp->h_length);
  321. //setting port
  322. server.sin_port = htons(m_port);
  323. /* make our socket (and leave it blocking) */
  324. if((m_write_socket = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
  325. perror("network_socket::connect(): socket() failed");
  326. throw new GeneralException("network_socket::connect connect() failed",__FILE__,__LINE__);
  327. }
  328. //same socket for read & write
  329. m_read_socket = m_write_socket;
  330. /*
  331. * hook it up
  332. */
  333. if(connect(m_write_socket, (struct sockaddr*)&server, sizeof(server)) == -1) {
  334. perror("network_socket::connect(): connect() failed");
  335. shutdown();
  336. throw new GeneralException("network_socket::connect(): connect() failed",__FILE__,__LINE__);
  337. }
  338. /*
  339. * read the banner from the server
  340. */
  341. if((numread = recv_packet(&banner[0],OVERFLOW_IDENT_STRLEN)) != OVERFLOW_IDENT_STRLEN) {
  342. perror("network_socket::connect(): read() failed");
  343. shutdown();
  344. throw new GeneralException("network_socket::connect(): read() failed",__FILE__,__LINE__);
  345. }
  346. /*
  347. * verify the banner (if it contains "OVERFLOW")
  348. */
  349. if (banner[0] != 'O' || banner[1] != 'V' || banner[2] != 'E' || banner[3] != 'R' ||
  350. banner[4] != 'F' || banner[5] != 'L' || banner[6] != 'O' || banner[7] != 'W') {
  351. shutdown();
  352. throw new GeneralException("network_socket::connect() does not contain the banner",__FILE__,__LINE__);
  353. }
  354. }
  355. /******************************************************************************
  356. Stream part!
  357. *******************************************************************************/
  358. socket_streambuf::socket_streambuf(int type, int port)
  359. : network_socket(type,port)
  360. , takeFromBuf(false) {
  361. }
  362. int socket_streambuf::overflow(int c)
  363. {
  364. send_packet((unsigned char*) &c, 1);
  365. //FIXME: Find EOF?
  366. return 0;
  367. }
  368. streamsize socket_streambuf::xsputn(const char *s, streamsize n) {
  369. return send_packet((unsigned char*) s, (size_t) n);
  370. }
  371. int socket_streambuf::uflow() {
  372. if (takeFromBuf) {
  373. takeFromBuf = false;
  374. return charBuf;
  375. } else {
  376. recv_packet((unsigned char*) &charBuf, 1);
  377. return charBuf;
  378. }
  379. }
  380. int socket_streambuf::underflow() {
  381. if (takeFromBuf) {
  382. return charBuf;
  383. }
  384. else {
  385. recv_packet((unsigned char*) &charBuf, 1);
  386. takeFromBuf = true;
  387. return charBuf;
  388. }
  389. }
  390. int socket_streambuf::pbackfail(int c) {
  391. if (!takeFromBuf) {
  392. if (c != EOF)
  393. charBuf = c;
  394. takeFromBuf = true;
  395. return charBuf;
  396. } else {
  397. return EOF;
  398. }
  399. }
  400. streamsize socket_streambuf::xsgetn(char *s, streamsize n) {
  401. return recv_packet((unsigned char*) s, (size_t) n);
  402. }