📄 remconn.cxx
字号:
/* * remconn.CXX * * Remote network connection (ppp) class implementation * * Portable Windows Library * * Copyright (c) 1993-1998 Equivalence Pty. Ltd. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is Portable Windows Library. * * The Initial Developer of the Original Code is Equivalence Pty. Ltd. * * Portions are Copyright (C) 1993 Free Software Foundation, Inc. * All Rights Reserved. * * Contributor(s): ______________________________________. * * $Log: remconn.cxx,v $ * Revision 1.17 1998/11/30 21:51:49 robertj * New directory structure. * * Revision 1.16 1998/09/24 04:12:15 robertj * Added open software license. * */#pragma implementation "remconn.h"#include <ptlib.h>#include <ptlib/pipechan.h>#include <ptlib/remconn.h>#include <stdio.h>#include <sys/ioctl.h>#include <sys/socket.h>#include "uerror.h"static const PString RasStr = "ras";static const PString NumberStr = "Number";static const PCaselessString UsernameStr = "$USERID";static const PCaselessString PasswordStr = "$PASSWORD";static const PString AddressStr = "Address";static const PString NameServerStr = "NameServer";static const PString OptionsStr = "Options";static const PString DeviceStr = "Device";static const PString DefaultDevice = "ppp0";static const PString PPPDStr = "PPPD";static const PString DefaultPPPD = "pppd";static const PString ChatStr = "Chat";static const PString DefaultChat = "chat";static const PString PortStr = "Port";static const PString DefaultPort = "/dev/modem";static const PString DialPrefixStr = "DialPrefix";static const PString DefaultDialPrefix = "ATDT";static const PString LoginStr = "Login";static const PString DefaultLogin = "'' sername: $USERID assword: $PASSWORD";static const PString TimeoutStr = "TimeoutStr";static const PString DefaultTimeout = "90";static const PString PPPDOptsStr = "PPPDOpts";static const PString PPPDOpts = "-detach";static const PString DefaultPPPDOpts = "crtscts modem defaultroute lock";static const PString BaudRateStr = "BaudRate";static const PString DefaultBaudRate = "57600";static const PString ErrorsStr = "Errors";static const PString DefaultErrors = "ABORT 'NO CARRIER' ABORT BUSY ABORT 'NO DIALTONE'";static const PString InitStr = "Init";static const PString DefaultInit = "'' ATE1Q0Z OK";static const PXErrorStruct ErrorTable[] ={ // Remote connection errors { 1000, "Attempt to open remote connection with empty system name" }, { 1001, "Attempt to open connection to unknown remote system"}, { 1002, "pppd could not connect to remote system"},};static int PPPDeviceStatus(const char * devName);PRemoteConnection::PRemoteConnection(){ Construct();}PRemoteConnection::PRemoteConnection(const PString & name) : remoteName(name){ Construct();}PRemoteConnection::~PRemoteConnection(){ Close();}BOOL PRemoteConnection::Open(const PString & name, BOOL existing){ return Open(name, "", "", existing);}BOOL PRemoteConnection::Open(const PString & name, const PString & user, const PString & pword, BOOL existing){ userName = user; password = pword; // cannot open remote connection with an empty name if (name.IsEmpty()) { status = NoNameOrNumber; PProcess::PXShowSystemWarning(1000, ErrorTable[0].str); return FALSE; } // cannot open remote connection not in config file PConfig config(0, RasStr); PString phoneNumber; if ((phoneNumber = config.GetString(name, NumberStr, "")).IsEmpty()) { status = NoNameOrNumber; PProcess::PXShowSystemWarning(1001, ErrorTable[1].str); return FALSE; } // if there is a connection active, check to see if it has the same name if (pipeChannel != NULL && pipeChannel->IsRunning() && name == remoteName && PPPDeviceStatus(deviceStr) > 0) { osError = errno; status = Connected; return TRUE; } osError = errno; if (existing) return FALSE; Close(); // name = name of configuration // sectionName = name of config section remoteName = name; /////////////////////////////////////////// // // get global options // config.SetDefaultSection(OptionsStr); deviceStr = config.GetString(DeviceStr, DefaultDevice); PString pppdStr = config.GetString(PPPDStr, DefaultPPPD); PString chatStr = config.GetString(ChatStr, DefaultChat); PString baudRate = config.GetString(BaudRateStr, DefaultBaudRate); PString chatErrs = config.GetString(ErrorsStr, DefaultErrors); PString modemInit = config.GetString(InitStr, DefaultInit); PString dialPrefix = config.GetString(DialPrefixStr, DefaultDialPrefix); PString pppdOpts = config.GetString(PPPDOptsStr, DefaultPPPDOpts); /////////////////////////////////////////// // // get remote system parameters // config.SetDefaultSection(remoteName); PString portName = config.GetString(PortStr, config.GetString(OptionsStr, PortStr, DefaultPort)); PString loginStr = config.GetString(LoginStr, DefaultLogin); PString timeoutStr = config.GetString(TimeoutStr, DefaultTimeout); PINDEX timeout = timeoutStr.AsInteger(); PString addressStr = config.GetString(AddressStr, ""); PString nameServerStr = config.GetString(NameServerStr, ""); /////////////////////////////////////////// // // start constructing the command argument array // PStringArray argArray; PINDEX argCount = 0; argArray[argCount++] = portName; argArray[argCount++] = baudRate; PStringArray tokens = PPPDOpts.Tokenise(' '); PINDEX i; for (i = 0; i < tokens.GetSize(); i++) argArray[argCount++] = tokens[i]; tokens = pppdOpts.Tokenise(' '); for (i = 0; i < tokens.GetSize(); i++) argArray[argCount++] = tokens[i]; if (!nameServerStr.IsEmpty()) { argArray[argCount++] = "ipparam"; argArray[argCount++] = nameServerStr; } /////////////////////////////////////////// // // replace metastrings in the login string // loginStr.Replace(UsernameStr, user); loginStr.Replace(PasswordStr, pword); /////////////////////////////////////////// // // setup the chat command // PString chatCmd = chatErrs & modemInit & dialPrefix + phoneNumber & loginStr; if (!chatCmd.IsEmpty()) { argArray[argCount++] = "connect"; argArray[argCount++] = chatStr & "-t" + timeoutStr & chatCmd; } if (!addressStr) argArray[argCount++] = addressStr + ":"; /////////////////////////////////////////// // // instigate a dial using pppd // pipeChannel = PNEW PPipeChannel(pppdStr, argArray); osError = errno; /////////////////////////////////////////// // // wait until the dial succeeds, or times out // PTimer timer(timeout*1000); for (;;) { if (pipeChannel == NULL || !pipeChannel->IsRunning()) break; if (PPPDeviceStatus(deviceStr) > 0) { osError = errno; return TRUE; } if (!timer.IsRunning()) break; PThread::Current()->Sleep(1000); } osError = errno; /////////////////////////////////////////// // // dial failed // Close(); return FALSE;}PObject::Comparison PRemoteConnection::Compare(const PObject & obj) const{ return remoteName.Compare(((const PRemoteConnection &)obj).remoteName);}PINDEX PRemoteConnection::HashFunction() const{ return remoteName.HashFunction();}void PRemoteConnection::Construct(){ pipeChannel = NULL; status = Idle; osError = 0;}BOOL PRemoteConnection::Open(BOOL existing){ return Open(remoteName, existing);}void PRemoteConnection::Close(){ if (pipeChannel != NULL) { // give pppd a chance to clean up pipeChannel->Kill(SIGINT); PTimer timer(10*1000); for (;;) { if (!pipeChannel->IsRunning() || (PPPDeviceStatus(deviceStr) <= 0) || !timer.IsRunning()) break; PThread::Current()->Sleep(1000); } // kill the connection for real delete pipeChannel; pipeChannel = NULL; }}PRemoteConnection::Status PRemoteConnection::GetStatus() const{ if (pipeChannel != NULL && pipeChannel->IsRunning() && PPPDeviceStatus(deviceStr) > 0) return Connected; return Idle;}PStringArray PRemoteConnection::GetAvailableNames() { PStringArray names; // get the list of remote system names from the system config file PConfig config(0, RasStr); // remotes have section names of the form "Remote-x" where X is some // unique identifier, usually a number or the system name PStringList sections = config.GetSections(); for (PINDEX i = 0; i < sections.GetSize(); i++) { PString sectionName = sections[i]; if (sectionName != OptionsStr) names[names.GetSize()] = sectionName; } return names;}//// <0 = does not exist// 0 = exists, but is down// >0 = exists, is up//static int PPPDeviceStatus(const char * devName){#if defined(HAS_IFREQ) int skfd; struct ifreq ifr; // Create a channel to the NET kernel. if ((skfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) return -1; // attempt to get the status of the ppp connection int stat; strcpy(ifr.ifr_name, devName); if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) stat = -1; else stat = (ifr.ifr_flags & IFF_UP) ? 1 : 0; // attempt to get the status of the ppp connection close(skfd); return stat;#else#warning "No PPPDeviceExists implementation defined" return FALSE;#endif}PRemoteConnection::Status PRemoteConnection::GetConfiguration( Configuration & config // Configuration of remote connection ){ return GetConfiguration(remoteName, config);}PRemoteConnection::Status PRemoteConnection::GetConfiguration( const PString & name, // Remote connection name to get configuration Configuration & config // Configuration of remote connection ){ if (name.IsEmpty()) return NoNameOrNumber; PConfig cfg(0, RasStr); if (cfg.GetString(name, NumberStr, "").IsEmpty()) return NoNameOrNumber; cfg.SetDefaultSection(name); config.device = cfg.GetString(OptionsStr, PortStr, DefaultPort); config.phoneNumber = cfg.GetString(NumberStr); config.ipAddress = cfg.GetString(AddressStr); config.dnsAddress = cfg.GetString(NameServerStr); config.script = cfg.GetString(LoginStr, DefaultLogin); config.subEntries = 0; config.dialAllSubEntries = FALSE; return Connected;}PRemoteConnection::Status PRemoteConnection::SetConfiguration( const Configuration & config, // Configuration of remote connection BOOL create // Flag to create connection if not present ){ return SetConfiguration(remoteName, config, create);}PRemoteConnection::Status PRemoteConnection::SetConfiguration( const PString & name, // Remote connection name to configure const Configuration & config, // Configuration of remote connection BOOL create // Flag to create connection if not present ){ if (config.phoneNumber.IsEmpty()) return GeneralFailure; PConfig cfg(0, RasStr); if (!create && cfg.GetString(name, NumberStr, "").IsEmpty()) return NoNameOrNumber; cfg.SetDefaultSection(name); if (config.device.IsEmpty()) cfg.DeleteKey(PortStr); else cfg.SetString(PortStr, config.device); cfg.SetString(NumberStr, config.phoneNumber); if (config.ipAddress.IsEmpty()) cfg.DeleteKey(AddressStr); else cfg.SetString(AddressStr, config.ipAddress); if (config.dnsAddress.IsEmpty()) cfg.DeleteKey(NameServerStr); else cfg.SetString(NameServerStr, config.dnsAddress); if (config.script.IsEmpty()) cfg.DeleteKey(LoginStr); else cfg.SetString(LoginStr, config.script); return Connected;}PRemoteConnection::Status PRemoteConnection::RemoveConfiguration( const PString & name // Remote connection to remove ){ PConfig cfg(0, RasStr); if (cfg.GetString(name, NumberStr, "").IsEmpty()) return NoNameOrNumber; cfg.DeleteSection(name); return Connected;}// End of File ////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -