TCPSocket.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #ifndef BELL_BASIC_SOCKET_H
  2. #define BELL_BASIC_SOCKET_H
  3. #include <memory>
  4. #include <vector>
  5. #include <string>
  6. #include <iostream>
  7. #include <ctype.h>
  8. #include <cstring>
  9. #include <stdlib.h>
  10. #include <sys/types.h>
  11. #include <sys/socket.h>
  12. #include <netdb.h>
  13. #include <netinet/in.h>
  14. #include <unistd.h>
  15. #include <sstream>
  16. #include <fstream>
  17. #include <netinet/tcp.h>
  18. #include <BellLogger.h>
  19. namespace bell
  20. {
  21. class TCPSocket : public bell::Socket
  22. {
  23. private:
  24. int sockFd;
  25. bool isClosed = false;
  26. public:
  27. TCPSocket() {};
  28. ~TCPSocket() {
  29. close();
  30. };
  31. void open(std::string url)
  32. {
  33. // remove https or http from url
  34. url.erase(0, url.find("://") + 3);
  35. // split by first "/" in url
  36. std::string hostUrl = url.substr(0, url.find('/'));
  37. std::string pathUrl = url.substr(url.find('/'));
  38. std::string portString = "80";
  39. // check if hostUrl contains ':'
  40. if (hostUrl.find(':') != std::string::npos)
  41. {
  42. // split by ':'
  43. std::string host = hostUrl.substr(0, hostUrl.find(':'));
  44. portString = hostUrl.substr(hostUrl.find(':') + 1);
  45. hostUrl = host;
  46. }
  47. int domain = AF_INET;
  48. int socketType = SOCK_STREAM;
  49. addrinfo hints, *addr;
  50. //fine-tune hints according to which socket you want to open
  51. hints.ai_family = domain;
  52. hints.ai_socktype = socketType;
  53. hints.ai_protocol = IPPROTO_IP; // no enum : possible value can be read in /etc/protocols
  54. hints.ai_flags = AI_CANONNAME | AI_ALL | AI_ADDRCONFIG;
  55. BELL_LOG(info, "http", "%s %s", hostUrl.c_str(), portString.c_str());
  56. if (getaddrinfo(hostUrl.c_str(), portString.c_str(), &hints, &addr) != 0)
  57. {
  58. BELL_LOG(error, "webradio", "DNS lookup error");
  59. throw std::runtime_error("Resolve failed");
  60. }
  61. sockFd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
  62. if (connect(sockFd, addr->ai_addr, addr->ai_addrlen) < 0)
  63. {
  64. close();
  65. BELL_LOG(error, "http", "Could not connect to %s", url.c_str());
  66. throw std::runtime_error("Resolve failed");
  67. }
  68. int flag = 1;
  69. setsockopt(sockFd, /* socket affected */
  70. IPPROTO_TCP, /* set option at TCP level */
  71. TCP_NODELAY, /* name of option */
  72. (char *)&flag, /* the cast is historical cruft */
  73. sizeof(int)); /* length of option value */
  74. freeaddrinfo(addr);
  75. }
  76. size_t read(uint8_t *buf, size_t len) {
  77. return recv(sockFd, buf, len, 0);
  78. }
  79. size_t write(uint8_t *buf, size_t len) {
  80. return send(sockFd, buf, len, 0);
  81. }
  82. void close() {
  83. if (!isClosed) {
  84. ::close(sockFd);
  85. isClosed = true;
  86. }
  87. }
  88. };
  89. }
  90. #endif