/* * the::system::net::dns::getAddrInfo */ ADDRINFOW *the::system::net::dns::getAddrInfo(const wchar_t *hostNameOrAddress, const int addressFamily) { THE_STACK_TRACE; ADDRINFOW *retval = NULL; // Receives the address infos. ADDRINFOW hints; // The hints about the info we want. int err = 0; // Receives lookup error codes. /* * Set the lookup hints: * - The input string is either a host name or a human readable IP address. * - Return the addresses for any protocol family. */ the::zero_memory(&hints); hints.ai_flags = 0; //AI_CANONNAME | AI_NUMERICHOST; hints.ai_family = addressFamily; #if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0502)) if (::GetAddrInfoW(hostNameOrAddress, NULL, &hints, &retval) != 0) { #else /* (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0502)) */ if (::getaddrinfo(THE_W2A(hostNameOrAddress), NULL, &hints, &retval) != 0) { #endif /* (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0502)) */ ASSERT(retval == NULL); #ifdef _WIN32 throw socket_exception(__FILE__, __LINE__); #else /* _WIN32 */ throw socket_exception(err, ::gai_strerror(err), __FILE__, __LINE__); #endif /* _WIN32 */ } return retval; }
/* * the::system::net::dns::getAddrInfo */ struct addrinfo *the::system::net::dns::getAddrInfo(const char *hostNameOrAddress, const int addressFamily) { THE_STACK_TRACE; struct addrinfo *retval = NULL; // Receives the address infos. struct addrinfo hints; // The hints about the info we want. int err = 0; // Receives lookup error codes. /* * Set the lookup hints: * - The input string is either a host name or a human readable IP address. * - Return the addresses for any protocol family. */ the::zero_memory(&hints); hints.ai_flags = 0; //AI_CANONNAME | AI_NUMERICHOST; hints.ai_family = addressFamily; if ((err = ::getaddrinfo(hostNameOrAddress, NULL, &hints, &retval)) != 0) { ASSERT(retval == NULL); #ifdef _WIN32 throw socket_exception(__FILE__, __LINE__); #else /* _WIN32 */ throw socket_exception(err, ::gai_strerror(err), __FILE__, __LINE__); #endif /* _WIN32 */ } return retval; }
/** * @brief Receive data from socket * * ...and puts it in `buf`. * * @param buf A writable memory buffer of length `len` * @param len Length of `buf` * @param flags Flags for `recv(2)`. WARNING: Throws an exception if `recv()` returns -1; this may be the case if the flag `MSG_DONTWAIT` is used. * * @returns The length of received data */ ssize_t stream_client_socket::rcv(void* buf, size_t len, int flags) { ssize_t recvd; if ( shut_rd == true ) throw socket_exception(__FILE__,__LINE__,"stream_client_socket::rcv() - Socket has already been shut down!",false); if ( sfd == -1 ) throw socket_exception(__FILE__,__LINE__,"stream_client_socket::rcv() - Socket is not connected!",false); if ( buf == NULL || len == 0 ) throw socket_exception(__FILE__,__LINE__,"stream_client_socket::rcv() - Buffer or length is null!",false); memset(buf,0,len); if ( -1 == (recvd = BERKELEY::recv(sfd,buf,len,flags)) ) { if ( is_nonblocking && errno == EWOULDBLOCK ) return -1; else throw socket_exception(__FILE__,__LINE__,"stream_client_socket::rcv() - Error while reading!"); } return recvd; }
void generic_socket::reuse() { int on = 1; if (bound_ != 0) throw socket_exception("can't set reuse, socket is not bound yet"); if ( setsockopt(socket_descriptor_, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(on)) == -1) throw socket_exception(strerror(errno)); }
/** * @brief Connect a UNIX datagram socket * * This function connects a datagram socket; `connect(2)` says the following about this: * * > If the socket sockfd is of type SOCK_DGRAM then addr is the address to which datagrams are sent by default, and the only address from which datagrams are received. * * @param path The path of the socket to connect this socket to. */ void unix_dgram_client::connect(const char* path) { if ( sfd == -1 ) throw socket_exception(__FILE__,__LINE__,"unix_dgram_client::connect() - Socket has already been closed!",false); if ( connect_unix_dgram_socket(sfd,path) < 0 ) throw socket_exception(__FILE__,__LINE__,"unix_dgram_client::connect: Could not connect dgram socket!"); _path.assign(path); connected = true; }
void generic_socket::non_blocking() { int flags; flags = fcntl(socket_descriptor_, F_GETFL); if (flags == -1) throw socket_exception(strerror(errno)); flags |= O_NONBLOCK; if (fcntl(socket_descriptor_, F_SETFL, flags) == -1) throw socket_exception(strerror(errno)); }
/** * @brief Set a UNIX domain datagram socket up * * @param path The path to bind this socket to * @param flags Flags for `socket(2)` */ void unix_dgram_client::setup(const char* path, int flags) { if ( sfd != -1 ) throw socket_exception(__FILE__,__LINE__,"unix_dgram_client::unix_dgram_client: Socket is already set up!\n"); sfd = create_unix_dgram_socket(path,flags); if ( path ) _path.assign(path); if ( sfd < 0 ) throw socket_exception(__FILE__,__LINE__,"unix_dgram_client::unix_dgram_client: Could not create unix dgram client socket!\n"); }
void curl_set_opt_num(CURL *curl, CURLoption option, long number) { CURLcode code = curl_easy_setopt(curl, option, number); if (code != CURLE_OK) { throw socket_exception(curl_easy_strerror(code)); } }
void SocketSet::poll( socket_ptr_list* readable_list_ptr, socket_ptr_list* writable_list_ptr, socket_ptr_list* exception_list_ptr ) { if( m_sockets.empty() ) return; if(readable_list_ptr) readable_list_ptr->clear(); if(writable_list_ptr) writable_list_ptr->clear(); if(exception_list_ptr) exception_list_ptr->clear(); int max_fd_plus1 = m_sockets.rbegin()->first + 1; clear_flag(); int n; if( timeout_.tv_sec < 0 ) n = ::select( max_fd_plus1, &m_fdSet_r, &m_fdSet_w, &m_fdSet_e, 0); else n = ::select( max_fd_plus1, &m_fdSet_r, &m_fdSet_w, &m_fdSet_e, &timeout_); if( n > 0 ){ for( socket_map::const_iterator iter = m_sockets.begin(); iter != m_sockets.end(); ++iter ){ if( readable_list_ptr && FD_ISSET( iter->first, &m_fdSet_r ) ) readable_list_ptr->push_back( iter->second ); if( writable_list_ptr && FD_ISSET( iter->first, &m_fdSet_w ) ) writable_list_ptr->push_back( iter->second ); if( exception_list_ptr && FD_ISSET( iter->first, &m_fdSet_e ) ) exception_list_ptr->push_back( iter->second ); } } else if( n < 0) throw socket_exception("select(2)", errno); }
/** * @brief Set a UNIX domain datagram socket up * * @param path The path to bind this socket to * @param flags Flags for `socket(2)` */ void unix_dgram_client::setup(const char* path, int flags) { if ( sfd != -1 ) throw socket_exception(__FILE__,__LINE__,"unix_dgram_client::unix_dgram_client: Socket has already been set up!",false); sfd = create_unix_dgram_socket(path,flags); if ( sfd < 0 ) throw socket_exception(__FILE__,__LINE__,"unix_dgram_client::unix_dgram_client: Could not create unix dgram client socket!"); if ( path ) _path.assign(path); is_nonblocking = flags & SOCK_NONBLOCK; }
void curl_set_opt(CURL *curl, CURLoption option, const void *value) { CURLcode code = curl_easy_setopt(curl, option, value); if (code != CURLE_OK) { throw socket_exception(curl_easy_strerror(code)); } }
void curl_set_opt_fun(CURL *curl, CURLoption option, size_t (*value)(void *, size_t, size_t, string *)) { CURLcode code = curl_easy_setopt(curl, option, value); if (code != CURLE_OK) { throw socket_exception(curl_easy_strerror(code)); } }
/** * @brief Disconnect a UNIX datagram socket * * Disconnects a previously connected socket. * */ void unix_dgram_client::deconnect(void) { if ( connect_unix_dgram_socket(sfd,0) < 0 ) throw socket_exception(__FILE__,__LINE__,"unix_dgram_client::deconnect: Could not disconnect dgram socket!"); _path.clear(); connected = false; }
int tcp_socket::recv(char* buffer, int max_len) { int res = ::recv(_sock_fd, buffer, max_len, 0); if (res == -1 ) throw socket_exception(system::error_code(errno)); //LOG_DEBUG(main_logger, "size:%d.", res); return res; }
int tcp_socket::send(const char* buffer, int size) { int res = comno::send(_sock_fd, buffer, size); if (res == -1 ) throw socket_exception(system::error_code(errno)); //LOG_DEBUG(main_logger, "size:%d.", res); return res; }
ssize_t stream_client_socket::rcv(void* buf, size_t len, int flags) { ssize_t recvd; if ( shut_rd == true ) throw socket_exception(__FILE__,__LINE__,"stream_client_socket::rcv() - Socket has already been shut down!\n"); if ( sfd == -1 ) throw socket_exception(__FILE__,__LINE__,"stream_client_socket::rcv() - Socket is not connected!\n"); if ( buf == NULL || len == 0 ) throw socket_exception(__FILE__,__LINE__,"stream_client_socket::rcv() - Buffer or length is null!\n"); memset(buf,0,len); if ( -1 == (recvd = recv(sfd,buf,len,flags)) ) throw socket_exception(__FILE__,__LINE__,"stream_client_socket::rcv() - Error while reading!\n"); return recvd; }
void tcp_server::bind(const unsigned int port) { struct sockaddr_in serverAddr; memset(&serverAddr, 0, sizeof(serverAddr)); serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); serverAddr.sin_port = htons(port); int res = ::bind(_sock_fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); if( res == -1 ) throw socket_exception(system::error_code(errno)); }
typename selectset<SockT>::ready_socks selectset<SockT>::wait(long long microsecs) { int n = 0; struct timeval *timeout = NULL; if ( microsecs != 0 ) { struct timeval _timeout; timeout = &_timeout; long long micropart = microsecs % 1000000; long long secpart = microsecs / 1000000; _timeout.tv_sec = secpart; _timeout.tv_usec = micropart; } n = select(highestfd(filedescriptors)+1,&readset,&writeset,NULL,timeout); ready_socks rwfds; if ( n < 0 ) { std::string err(strerror(errno)); throw socket_exception(__FILE__,__LINE__,"selectset::wait(): Error at select(): " + err); } else if ( n == 0 ) // time is over, no filedescriptor is ready { rwfds.first.resize(0); rwfds.second.resize(0); return rwfds; } std::vector<int>::iterator end = filedescriptors.end(); for ( std::vector<int>::iterator cur = filedescriptors.begin(); cur != end; cur++ ) { if ( FD_ISSET(*cur,&readset) ) rwfds.first.push_back(fdsockmap[*cur]); if ( FD_ISSET(*cur,&writeset) ) rwfds.second.push_back(fdsockmap[*cur]); } return rwfds; }
bool tcp_server::listen(const unsigned int port) { if (_sock_fd < 0) return false; bind(port); int res = ::listen(_sock_fd, 10); if (res < 0) { throw socket_exception(system::error_code(errno)); } _listen_port = port; return true; }
tcp_client tcp_server::accept() { struct sockaddr_in clientAddr; socklen_t cliLen = sizeof(clientAddr); int clientSocket = ::accept(_sock_fd, (struct sockaddr *)&clientAddr, &cliLen); if (clientSocket == -1 ) { throw socket_exception(system::error_code(errno)); } end_point dest, src; dest.port = listen_port(); src.ip = ::inet_ntoa(clientAddr.sin_addr); return tcp_client(clientSocket, src, dest); }
std::string request(http::client &client, http::method method, const std::string &userPath) { throw socket_exception("curl implementation not enabled"); }
std::string request(http::client &client, http::method method, const std::string &userPath) { CURLcode code; char buf[http::MAX_URL_LEN + 1] = {0}; struct curl_slist *headers = NULL; CURL *curl = NULL; std::string path = userPath; net::uri uri = client.uri(); std::string content = client.content(); std::string response; curl = curl_easy_init(); if (curl == NULL) { throw socket_exception("unable to initialize curl request"); } // check if a path was specified if (path.empty()) { path = uri.full_path(); } if (path.empty()) { snprintf(buf, http::MAX_URL_LEN, "%s://%s", uri.scheme().c_str(), uri.host_with_port().c_str()); } else if (path[0] == '/') { snprintf(buf, http::MAX_URL_LEN, "%s://%s%s", uri.scheme().c_str(), uri.host_with_port().c_str(), path.c_str()); } else { snprintf(buf, http::MAX_URL_LEN, "%s://%s/%s", uri.scheme().c_str(), uri.host_with_port().c_str(), path.c_str()); } helper::curl_set_opt(curl, CURLOPT_URL, buf); helper::curl_set_opt_fun(curl, CURLOPT_WRITEFUNCTION, helper::curl_append_response_callback); helper::curl_set_opt_num(curl, CURLOPT_HEADER, 1L); #ifdef DEBUG helper::curl_set_opt_num(curl, CURLOPT_VERBOSE, 1L); #endif switch (method) { case http::GET: helper::curl_set_opt_num(curl, CURLOPT_HTTPGET, 1L); break; case http::POST: helper::curl_set_opt_num(curl, CURLOPT_POST, 1L); if (!content.empty()) { helper::curl_set_opt(curl, CURLOPT_POSTFIELDS, content.c_str()); helper::curl_set_opt_num(curl, CURLOPT_POSTFIELDSIZE, content.size()); } break; case http::PUT: helper::curl_set_opt_num(curl, CURLOPT_PUT, 1L); if (!content.empty()) { helper::curl_set_opt(curl, CURLOPT_POSTFIELDS, content.c_str()); helper::curl_set_opt_num(curl, CURLOPT_POSTFIELDSIZE, content.size()); } break; default: helper::curl_set_opt(curl, CURLOPT_CUSTOMREQUEST, http::method_names[method]); break; } for (auto &h : client.headers()) { snprintf(buf, http::MAX_URL_LEN, "%s: %s", h.first.c_str(), h.second.c_str()); headers = curl_slist_append(headers, buf); } helper::curl_set_opt(curl, CURLOPT_HTTPHEADER, headers); helper::curl_set_opt_num(curl, CURLOPT_TIMEOUT, client.timeout()); helper::curl_set_opt(curl, CURLOPT_WRITEDATA, &response); CURLcode res = curl_easy_perform(curl); curl_slist_free_all(headers); if (res != CURLE_OK && res != CURLE_PARTIAL_FILE) { curl_easy_cleanup(curl); throw socket_exception(curl_easy_strerror(res)); } curl_easy_cleanup(curl); return response; }
std::string request(http::client &client, http::method method, const string &userPath) { char buf[http::MAX_URL_LEN + 1] = {0}; buffered_socket sock; std::string path = userPath; net::uri uri = client.uri(); std::string content = client.content(); if (client.is_secure()) { sock.set_secure(true); } if (!uri.port().empty()) { int port = stoi(uri.port()); if (!sock.connect(uri.host(), port)) { throw socket_exception("unable to connect to " + uri.to_string()); } } else { if (!sock.connect(uri.host(), client.is_secure() ? http::DEFAULT_SECURE_PORT : http::DEFAULT_PORT)) { throw socket_exception("unable to connect to " + uri.to_string()); } } if (path.empty()) { path = uri.full_path(); } // send the method and path if (path.empty()) snprintf(buf, http::MAX_URL_LEN, http::REQUEST_PREAMBLE, http::method_names[method], "/", client.version().c_str()); else if (path[0] == '/') snprintf(buf, http::MAX_URL_LEN, http::REQUEST_PREAMBLE, http::method_names[method], path.c_str(), client.version().c_str()); else snprintf(buf, http::MAX_URL_LEN, http::REQUEST_PREAMBLE, http::method_names[method], ("/" + path).c_str(), client.version().c_str()); sock.writeln(buf); bool chunked = client.has_header(http::HEADER_TRANSFER_ENCODING) && !strcasecmp(client.header(http::HEADER_TRANSFER_ENCODING).c_str(), "chunked"); // specify the host if (!client.has_header(http::HEADER_HOST)) { snprintf(buf, http::MAX_URL_LEN, "%s: %s", http::HEADER_HOST, uri.host().c_str()); sock.writeln(buf); } if (!client.has_header(http::HEADER_ACCEPT)) { snprintf(buf, http::MAX_URL_LEN, "%s: */*", http::HEADER_ACCEPT); sock.writeln(buf); } if (!client.has_header(http::HEADER_CONNECTION)) { snprintf(buf, http::MAX_URL_LEN, "%s: close", http::HEADER_CONNECTION); sock.writeln(buf); } // add the headers for (const auto &h : client.headers()) { snprintf(buf, http::MAX_URL_LEN, "%s: %s", h.first.c_str(), h.second.c_str()); sock.writeln(buf); } // if we have a content, add the size if (!chunked && !content.empty()) { snprintf(buf, http::MAX_URL_LEN, "%s: %zu", http::HEADER_CONTENT_SIZE, content.size()); sock.writeln(buf); } // finish header sock.writeln(); // add the content if (!content.empty()) { sock.write(content); } #ifdef DEBUG cout << string(sock.output().begin(), sock.output().end()); #endif if (!sock.write_from_buffer()) { throw socket_exception("unable to write to socket"); } if (!sock.read_to_buffer()) { throw socket_exception("unable to read from socket"); } auto input = sock.input(); return string(input.begin(), input.end()); }