X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6782163029fb63715ee833ff723b3fae6a21cf6e..1c8515f9ab86415068e779ce76a7268521e12192:/src/unix/net.cpp diff --git a/src/unix/net.cpp b/src/unix/net.cpp new file mode 100644 index 0000000000..04369bb929 --- /dev/null +++ b/src/unix/net.cpp @@ -0,0 +1,379 @@ +// -*- c++ -*- /////////////////////////////////////////////////////////////// +// Name: unix/net.cpp +// Purpose: Network related wxWindows classes and functions +// Author: Karsten Ballüder +// Modified by: +// Created: 03.10.99 +// RCS-ID: $Id$ +// Copyright: (c) Karsten Ballüder +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#include "wx/setup.h" + +#if wxUSE_DIALUP_MANAGER + +#ifndef WX_PRECOMP +# include "wx/defs.h" +#endif // !PCH + +#include "wx/string.h" +#include "wx/event.h" +#include "wx/net.h" +#include "wx/timer.h" +#include "wx/filefn.h" +#include "wx/utils.h" +#include "wx/log.h" + +#include + +#include +#include +#include +#define __STRICT_ANSI__ +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- +// A class which groups functions dealing with connecting to the network from a +// workstation using dial-up access to the net. There is at most one instance +// of this class in the program accessed via GetDialUpManager(). +// ---------------------------------------------------------------------------- + +/* TODO + * + * 1. more configurability for Unix: i.e. how to initiate the connection, how + * to check for online status, &c. + * 2. add a "long Dial(long connectionId = -1)" function which asks the user + * about which connection to dial (this may be done using native dialogs + * under NT, need generic dialogs for all others) and returns the identifier + * of the selected connection (it's opaque to the application) - it may be + * reused later to dial the same connection later (or use strings instead of + * longs may be?) + * 3. add an async version of dialing functions which notify the caller about + * the progress (or may be even start another thread to monitor it) + * 4. the static creation/accessor functions are not MT-safe - but is this + * really crucial? I think we may suppose they're always called from the + * main thread? + */ + +class WXDLLEXPORT wxDialUpManagerImpl : public wxDialUpManager +{ +public: + wxDialUpManagerImpl() + { + m_IsOnline = -1; // unknown + m_timer = NULL; + m_CanUseIfconfig = -1; // unknown + m_BeaconHost = WXDIALUP_MANAGER_DEFAULT_BEACONHOST; + m_BeaconPort = 80; + } + + /** Could the dialup manager be initialized correctly? If this function + returns FALSE, no other functions will work neither, so it's a good idea + to call this function and check its result before calling any other + wxDialUpManager methods. + */ + virtual bool IsOk() const + { return TRUE; } + + /** The simplest way to initiate a dial up: this function dials the given + ISP (exact meaning of the parameter depends on the platform), returns + TRUE on success or FALSE on failure and logs the appropriate error + message in the latter case. + @param nameOfISP optional paramater for dial program + @param username unused + @param password unused + */ + virtual bool Dial(const wxString& nameOfISP, + const wxString& WXUNUSED(username), + const wxString& WXUNUSED(password)); + + /// Hang up the currently active dial up connection. + virtual bool HangUp(); + + // returns TRUE if the computer is connected to the network: under Windows, + // this just means that a RAS connection exists, under Unix we check that + // the "well-known host" (as specified by SetWellKnownHost) is reachable + virtual bool IsOnline() const + { + if( (! m_timer) // we are not polling, so test now: + || m_IsOnline == -1 + ) + CheckStatus(); + return m_IsOnline != 0; + } + + // sometimes the built-in logic for determining the online status may fail, + // so, in general, the user should be allowed to override it. This function + // allows to forcefully set the online status - whatever our internal + // algorithm may think about it. + virtual void SetOnlineStatus(bool isOnline = TRUE) + { m_IsOnline = isOnline; } + + // set misc wxDialUpManager options + // -------------------------------- + + // enable automatical checks for the connection status and sending of + // wxEVT_DIALUP_CONNECTED/wxEVT_DIALUP_DISCONNECTED events. The interval + // parameter is only for Unix where we do the check manually: under + // Windows, the notification about the change of connection status is + // instantenous. + // + // Returns FALSE if couldn't set up automatic check for online status. + virtual bool EnableAutoCheckOnlineStatus(size_t nSeconds); + + // disable automatic check for connection status change - notice that the + // wxEVT_DIALUP_XXX events won't be sent any more neither. + virtual void DisableAutoCheckOnlineStatus(); + + // under Unix, the value of well-known host is used to check whether we're + // connected to the internet. It's unused under Windows, but this function + // is always safe to call. The default value is www.yahoo.com. + virtual void SetWellKnownHost(const wxString& hostname, + int portno = 80); + /** Sets the commands to start up the network and to hang up + again. Used by the Unix implementations only. + */ + virtual void SetConnectCommand(const wxString &command, const wxString &hupcmd) + { m_ConnectCommand = command; m_HangUpCommand = hupcmd; } + +private: + /// -1: don´t know, 0 = no, 1 = yes + int m_IsOnline; + + /// Can we use ifconfig to list active devices? + int m_CanUseIfconfig; + /// The path to ifconfig + wxString m_IfconfigPath; + + /// beacon host: + wxString m_BeaconHost; + /// beacon host portnumber for connect: + int m_BeaconPort; + + /// command to connect to network + wxString m_ConnectCommand; + /// command to hang up + wxString m_HangUpCommand; + /// name of ISP + wxString m_ISPname; + /// a timer for regular testing + class AutoCheckTimer *m_timer; + + friend class AutoCheckTimer; + /// determine status + void CheckStatus(void) const; + + /// real status check + void CheckStatusInternal(void); +}; + + +class AutoCheckTimer : public wxTimer +{ +public: + AutoCheckTimer(wxDialUpManagerImpl *dupman) + { + m_dupman = dupman; + m_started = FALSE; + } + + virtual bool Start( int millisecs = -1 ) + { m_started = TRUE; return wxTimer::Start(millisecs, FALSE); } + + virtual void Notify() + { wxLogTrace("Checking dial up network status."); m_dupman->CheckStatus(); } + + virtual void Stop() + { if ( m_started ) wxTimer::Stop(); } +public: + bool m_started; + wxDialUpManagerImpl *m_dupman; +}; + +bool +wxDialUpManagerImpl::Dial(const wxString &isp, + const wxString & WXUNUSED(username), + const wxString & WXUNUSED(password)) +{ + if(m_IsOnline == 1) + return FALSE; + m_IsOnline = -1; + m_ISPname = isp; + wxString cmd; + if(m_ConnectCommand.Find("%s")) + cmd.Printf(m_ConnectCommand,m_ISPname.c_str()); + else + cmd = m_ConnectCommand; + return wxExecute(cmd, /* sync */ TRUE) == 0; +} + +bool +wxDialUpManagerImpl::HangUp(void) +{ + if(m_IsOnline == 0) + return FALSE; + m_IsOnline = -1; + wxString cmd; + if(m_HangUpCommand.Find("%s")) + cmd.Printf(m_HangUpCommand,m_ISPname.c_str()); + else + cmd = m_HangUpCommand; + return wxExecute(cmd, /* sync */ TRUE) == 0; +} + + +bool +wxDialUpManagerImpl::EnableAutoCheckOnlineStatus(size_t nSeconds) +{ + wxASSERT(m_timer == NULL); + m_timer = new AutoCheckTimer(this); + bool rc = m_timer->Start(nSeconds*1000); + if(! rc) + { + delete m_timer; + m_timer = NULL; + } + return rc; +} + +void +wxDialUpManagerImpl::DisableAutoCheckOnlineStatus() +{ + wxASSERT(m_timer != NULL); + m_timer->Stop(); + delete m_timer; + m_timer = NULL; +} + + +void +wxDialUpManagerImpl::SetWellKnownHost(const wxString& hostname, int portno) +{ + /// does hostname contain a port number? + wxString port = hostname.After(':'); + if(port.Length()) + { + m_BeaconHost = hostname.Before(':'); + m_BeaconPort = atoi(port); + } + else + { + m_BeaconHost = hostname; + m_BeaconPort = portno; + } +} + + +void +wxDialUpManagerImpl::CheckStatus(void) const +{ + // This function calls the CheckStatusInternal() helper function + // which is OS - specific and then sends the events. + + int oldIsOnline = m_IsOnline; + ( /* non-const */ (wxDialUpManagerImpl *)this)->CheckStatusInternal(); + + // now send the events as appropriate: + if(m_IsOnline != oldIsOnline) + { + if(m_IsOnline) + ; // send ev + else + ; // send ev + } +} + +/* + We have three methods that we can use: + + 1. test via /sbin/ifconfig and grep for "sl", "ppp", "pl" + --> should be fast enough for regular polling + 2. test if we can reach the well known beacon host + --> too slow for polling + 3. check /proc/net/dev on linux?? + This method should be preferred, if possible. Need to do more + testing. + +*/ + +void +wxDialUpManagerImpl::CheckStatusInternal(void) +{ + m_IsOnline = -1; + + // First time check for ifconfig location. We only use the variant + // which does not take arguments, a la GNU. + if(m_CanUseIfconfig == -1) // unknown + { + if(wxFileExists("/sbin/ifconfig")) + m_IfconfigPath = "/sbin/ifconfig"; + else if(wxFileExists("/usr/sbin/ifconfig")) + m_IfconfigPath = "/usr/sbin/ifconfig"; + } + + // Let´s try the ifconfig method first, should be fastest: + if(m_CanUseIfconfig != 0) // unknown or yes + { + wxASSERT(m_IfconfigPath.length()); + + wxString tmpfile = wxGetTempFileName("_wxdialuptest"); + wxString cmd = m_IfconfigPath; + cmd << " >" << tmpfile; + if(wxExecute(m_IfconfigPath,TRUE /* sync */) == 0) + { + m_CanUseIfconfig = 1; + wxString cmd1 = "grep ppp <"+tmpfile; // PPP + wxString cmd2 = "grep sl <"+tmpfile; // SLIP + wxString cmd3 = "grep pl <"+tmpfile; // PLIP + if(wxExecute(cmd1,TRUE) == 0 + || wxExecute(cmd2,TRUE) == 0 + || wxExecute(cmd3,TRUE) == 0 + ) + m_IsOnline = 1; + } + else // could not run ifconfig correctly + m_CanUseIfconfig = 0; // don´t try again + wxRemoveFile(tmpfile); + if(m_IsOnline != -1) // we are done + return; + } + + // second method: try to connect to well known host: + struct hostent *hp; + struct sockaddr_in serv_addr; + int sockfd; + + m_IsOnline = 0; // assume false + if((hp = gethostbyname(m_BeaconHost)) == NULL) + return; // no DNS no net + + serv_addr.sin_family = hp->h_addrtype; + memcpy(&serv_addr.sin_addr,hp->h_addr, hp->h_length); + serv_addr.sin_port = htons(m_BeaconPort); + if( ( sockfd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) + { + // sys_error("cannot create socket for gw"); + return; + } + if( connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) + { + //sys_error("cannot connect to server"); + return; + } + //connected! + close(sockfd); +} + + +/* static */ +wxDialUpManager * +wxDialUpManager::wxDialUpManager::Create(void) +{ + return new wxDialUpManagerImpl; +} + +#endif // wxUSE_DIALUP_MANAGER