void TcpClientBase::connect(const IpAddress& remote_ip, uint16_t remote_port) { con->setRemoteAddr(remote_ip); remote_host = remote_ip.toString(); con->setRemotePort(remote_port); connect(); } /* TcpClientBase::connect */
TcpClient::TcpClient(const IpAddress& remote_ip, uint16_t remote_port, size_t recv_buf_len) : TcpConnection(recv_buf_len), dns(0), remote_host(remote_ip.toString()), sock(-1), wr_watch(0) { setRemoteAddr(remote_ip); setRemotePort(remote_port); } /* TcpClient::TcpClient */
TcpClientBase::TcpClientBase(TcpConnection *con, const IpAddress& remote_ip, uint16_t remote_port) : con(con), dns(0), remote_host(remote_ip.toString()), sock(-1), wr_watch(0) { con->setRemoteAddr(remote_ip); con->setRemotePort(remote_port); wr_watch = new FdWatch; wr_watch->activity.connect(mem_fun(*this, &TcpClientBase::connectHandler)); } /* TcpClientBase::TcpClientBase */
MacAddress MacAddress::lookup_from_ip_with_arp_table(const IpAddress& ipAddress, bool ping) { if(!ipAddress.isValid()) { return MacAddress(); } char line[500]; char ip_address[500]; int hw_type; int flags; char mac_address[500]; char mask[500]; char device[500]; MacAddress foundMac; if (ping) { ipAddress.ping(1000); } // ARP Table Reading Suggestion From // http://stackoverflow.com/a/21031888 FILE *fp = fopen("/proc/net/arp", "r"); fgets(line, sizeof(line), fp); // Skip the first line (column headers). while(fgets(line, sizeof(line), fp)) { sscanf(line, "%s 0x%x 0x%x %s %s %s\n", ip_address, &hw_type, &flags, mac_address, mask, device); if (ipAddress.toString().compare(ip_address) == 0) { foundMac = MacAddress(mac_address); break; } } fclose(fp); return foundMac; }
bool TcpServer::listen(const IpAddress& address, uint16_t port) { if(address.isNull()) return false; int fd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addr; bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); inet_pton(AF_INET, address.toString().c_str(), &addr.sin_addr); if(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == 0) { setServerAddress(address); setServerPort(port); setSocketDescriptor(fd); if(::listen(fd, SOMAXCONN) == 0) return true; } return false; }
void run() { // declare an instance of the USART and the stream that we'll use to write to it _usart=new MyUsart(57600); _outputStream=new UsartPollingOutputStream(*_usart); // declare the RTC that that stack requires. it's used for cache timeouts, DHCP lease expiry // and such like so it does not have to be calibrated for accuracy. A few seconds here or there // over a 24 hour period isn't going to make any difference. Start it ticking at zero which is // some way back in 2000 but that doesn't matter to us Rtc<RtcLsiClockFeature<Rtc32kHzLsiFrequencyProvider>,RtcSecondInterruptFeature> rtc; rtc.setTick(0); // declare an instance of the network stack MyNetworkStack::Parameters params; _net=new MyNetworkStack; // the stack requires the RTC params.base_rtc=&rtc; // It's nice to give the DHCP client a host name because then it'll show up in DHCP // 'active leases' page. In a home router this is often called 'attached devices' params.dhcp_hostname="stm32plus"; // spy on the DHCP announcements for DNS servers // by subscribing to the notification events passed around the network stack _net->NetworkNotificationEventSender.insertSubscriber( NetworkNotificationEventSourceSlot::bind(this,&NetDnsTest::onNotification) ); // subscribe to error events from the network stack _net->NetworkErrorEventSender.insertSubscriber( NetworkErrorEventSourceSlot::bind(this,&NetDnsTest::onError) ); // Initialise the stack. This will reset the PHY, initialise the MAC // and attempt to create a link to our link partner. Ensure your cable // is plugged in when you run this or be prepared to handle the error if(!_net->initialise(params)) error(); // start the ethernet MAC Tx/Rx DMA channels // this will trigger the DHCP transaction if(!_net->startup()) error(); // now query for google UK's host name (the default timeout is 5000ms, // configurable with 'dns_timeout' in the stack's parameters IpAddress ipAddress; char buf[30]; if(!_net->dnsHostnameQuery("www.google.co.uk",ipAddress)) error(); // write out the results ipAddress.toString(buf); *_outputStream << "www.google.co.uk = " << buf << "\r\n"; for(;;); }
Socket::Status TcpSocket::connect(const IpAddress& remoteAddress, unsigned short remotePort, Time timeout) { // Create the internal socket if it doesn't exist create(); if (isSecure()) { char port[5]; sprintf(port, "%d", remotePort); if (mbedtls_net_connect(&getSecureData().socket, remoteAddress.toString().c_str(), port, MBEDTLS_NET_PROTO_TCP) != 0) return priv::SocketImpl::getErrorStatus(); int ret; while((ret = mbedtls_ssl_handshake(&getSecureData().ssl)) != 0) if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) return Error; } else { // Create the remote address sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort); if (timeout <= Time::Zero) { // ----- We're not using a timeout: just try to connect ----- // Connect the socket if (::connect(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1) return priv::SocketImpl::getErrorStatus(); // Connection succeeded return Done; } else { // ----- We're using a timeout: we'll need a few tricks to make it work ----- // Save the previous blocking state bool blocking = isBlocking(); // Switch to non-blocking to enable our connection timeout if (blocking) setBlocking(false); // Try to connect to the remote address if (::connect(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) >= 0) { // We got instantly connected! (it may no happen a lot...) setBlocking(blocking); return Done; } // Get the error status Status status = priv::SocketImpl::getErrorStatus(); // If we were in non-blocking mode, return immediately if (!blocking) return status; // Otherwise, wait until something happens to our socket (success, timeout or error) if (status == Socket::NotReady) { // Setup the selector fd_set selector; FD_ZERO(&selector); FD_SET(getHandle(), &selector); // Setup the timeout timeval time; time.tv_sec = static_cast<long>(timeout.asMicroseconds() / 1000000); time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000); // Wait for something to write on our socket (which means that the connection request has returned) if (select(static_cast<int>(getHandle() + 1), NULL, &selector, NULL, &time) > 0) { // At this point the connection may have been either accepted or refused. // To know whether it's a success or a failure, we must check the address of the connected peer if (getRemoteAddress() != cpp3ds::IpAddress::None) { // Connection accepted status = Done; } else { // Connection refused status = priv::SocketImpl::getErrorStatus(); } } else { // Failed to connect before timeout is over status = priv::SocketImpl::getErrorStatus(); } } // Switch back to blocking mode setBlocking(true); return status; } } }