📄 epocnet.cpp
字号:
/* epocnet.cpp * * Symbian OS implementation of PuTTY networking support * * Mostly copied from the SyOSsh EPOC Release 5 port by Gabor Keresztfalvi, * some additional fixes for the current Symbian port by Petteri Kangaslampi. * I/O server stuff included in the SyOSsh version removed. * Originally baset on winnet.c in the PuTTY distribution. * * [No copyright messages in the original, assumed to be copyrighted by * Gabor Keresztfavli and available through the PuTTY license] * * Portions copyright 2002-2004 Petteri Kangaslampi * * See license.txt for full copyright and license information.*//* * SymbianOS (EPOC) networking abstraction. Version 2. Uses ActiveObjects... * FIXME: * - On MARM lookup of a valid IP number fails if having DNS server? */#ifdef PUTTY_IPV6#define IPV6 1#endif#include <e32std.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <netinet/in.h>#include <sys/socket.h>#include <assert.h>#include <in_iface.h>#ifdef __cplusplusextern "C" {#endif#define DEFINE_PLUG_METHOD_MACROS#include "putty.h"#include "network.h"#include "tree234.h"#include "ssh.h"#ifdef __cplusplus}#endif#include "epocnet.h"#include "charutil.h"#define DEBUGLOG#define ipv4_is_loopback(addr) \ ((ntohl(addr.s_addr) & 0xFF000000L) == 0x7F000000L)struct Socket_tag { const struct socket_function_table *fn; /* the above variable absolutely *must* be the first in this structure */ const char *error; RSocketS *s; Plug plug; void *private_ptr; bufchain output_data; int connected; int writable; int frozen; /* this causes readability notifications to be ignored */ int frozen_readable; /* this means we missed at least one readability * notification while we were frozen */ int localhost_only; /* for listening sockets */ int listening; /* for listening sockets */ RSocketS *accepted; char oobdata[1]; int sending_oob; int oobinline; int pending_error; /* in case send() returns error */ int killing; /* In case we have data to send... */};/* * We used to typedef struct Socket_tag *Socket. * * Since we have made the networking abstraction slightly more * abstract, Socket no longer means a tcp socket (it could mean * an ssl socket). So now we must use Actual_Socket when we know * we are talking about a tcp socket. */typedef struct Socket_tag *Actual_Socket;struct SockAddr_tag { const char *error; TUint family; TInetAddr *address; /* Address IPv4 style. */ char hostname[512]; /* Store an unresolved host name. */ };struct TNetStatics { tree234 *iSocketTree; RSocketServ iSocketServ; TInt iNextId; MSocketWatcher *iWatcher; void *iLogCtx; char iErrorMsg[256];};#define netStatics ((TNetStatics *const)((SymbianStatics *const)statics()->platform)->net_state)static int cmpfortree(void *av, void *bv){ Actual_Socket a = (Actual_Socket) av, b = (Actual_Socket) bv; unsigned long as = (unsigned long) a->s->id, bs = (unsigned long) b->s->id; if (as < bs) return -1; if (as > bs) return +1; return 0;}static int cmpforsearch(void *av, void *bv){ Actual_Socket b = (Actual_Socket) bv; unsigned long as = (unsigned long) ((RSocketS *)av)->id, bs = (unsigned long) b->s->id; if (as < bs) return -1; if (as > bs) return +1; return 0;}void sk_init(void){ TNetStatics *statics = new TNetStatics; if ( !statics ) fatalbox("Out of memory"); statics->iSocketTree = NULL; statics->iNextId = 1; statics->iWatcher = NULL; statics->iLogCtx = NULL; ((SymbianStatics*)statics()->platform)->net_state = statics; TInt err = netStatics->iSocketServ.Connect(2*MAXSOCKETS); if ( err != KErrNone ) fatalbox("Unable to connect to socket server"); netStatics->iSocketTree = newtree234(cmpfortree);}void sk_cleanup(void){ Socket s; int i; TNetStatics *statics = ((TNetStatics *)((SymbianStatics *)statics()->platform)->net_state); if ( statics->iSocketTree ) { for ( i = 0; (s = (Socket)index234(statics->iSocketTree, i)) != NULL; i++ ) { sk_close(s); } statics->iSocketServ.Close(); freetree234(statics->iSocketTree); statics->iSocketTree = NULL; } delete statics; ((SymbianStatics*)statics()->platform)->net_state = NULL;}// Set watcher object. Set to NULL to disable.void sk_set_watcher(MSocketWatcher *aWatcher) { netStatics->iWatcher = aWatcher;}void sk_provide_logctx(void *aLogCtx) { netStatics->iLogCtx = aLogCtx;}// Log an event#ifdef DEBUGLOGstatic void logeventf(const char *fmt, ...) { if ( !netStatics->iLogCtx ) return; va_list ap; char *buf; va_start(ap, fmt); buf = dupvprintf(fmt, ap); va_end(ap); log_eventlog(netStatics->iLogCtx, buf); sfree(buf); }#define LOGF(x) logeventf x#else#define LOGF(x)#endifstruct TErrorMessage { TInt iError; const char *iMessage;};static const TErrorMessage KErrorMessages[] = { { KErrNotFound, "Not found" }, { KErrCancel, "Operation cancelled" }, { KErrNoMemory, "Out of memory" }, { KErrNotSupported, "Not supported" }, { KErrInUse, "Already in use" }, { KErrNotReady, "Not ready" }, { KErrCorrupt, "Corrupted" }, { KErrBadName, "Bad name" }, { KErrAccessDenied, "Access denied" }, { KErrTimedOut, "Timed out" }, { KErrAbort, "Aborted" }, { KErrCouldNotConnect, "Could not connect" }, { KErrCouldNotDisconnect, "Could not disconnect" }, { KErrNetUnreach, "Network unreachable" }, { KErrHostUnreach, "Host unreachable" }, { KErrNoProtocolOpt, "No such protocol option" }, { KErrUrgentData, "Urgent data arrived" }, { KErrIfAuthenticationFailure, "Authentication failure" }, { KErrIfAuthNotSecure, "Authentication not secure" }, { KErrIfAccountDisabled, "Account disabled" }, { KErrIfRestrictedLogonHours, "Restricted logon hours" }, { KErrIfPasswdExpired, "Password expired" }, { KErrIfNoDialInPermission, "No dial-in permission" }, { KErrIfChangingPassword, "Changing password" }, { KErrIfCallbackNotAcceptable, "Callback not acceptable" }, { KErrIfDNSNotFound, "Host not found" }, { KErrIfLRDBadLine, "KErrIfLRDBadLine" }, { 0, NULL }};static char *FormatError(const char *operation, TInt error) { const char *msg; int i = 0; while ( (KErrorMessages[i].iError != error) && (KErrorMessages[i].iError != 0) ) { i++; } if ( KErrorMessages[i].iError == error ) { msg = KErrorMessages[i].iMessage; } else { msg = "Unknown error"; } snprintf(netStatics->iErrorMsg, sizeof(netStatics->iErrorMsg), "%s failed: %s (%d)", operation, msg, error); return netStatics->iErrorMsg;}SockAddr sk_namelookup(const char *host, char **canonicalname){ SockAddr ret = (SockAddr) smalloc(sizeof(struct SockAddr_tag)); RHostResolver hres; TNameEntry nameres; TNameRecord namerec; THostName thehostname; TInt err; LOGF(("sk_namelookup: Looking up %s", host)); memset(ret, 0, sizeof(struct SockAddr_tag)); ret->family = KAfInet; ret->address=new TInetAddr(); if (ret->address==NULL) { ret->error="Not enough memory to allocate TInetAddr."; return ret; } err=hres.Open(netStatics->iSocketServ, KAfInet, KProtocolInetUdp); if (err!=KErrNone) { ret->error = FormatError("Resolver open", err); LOGF(("sk_namelookup: RHostResolver.Open failed: %d, %s", err, ret->error)); delete ret->address; ret->address=NULL; return ret; } TPtr *hostDes = CreateDes(host); err=hres.GetByName(*hostDes,nameres); DeleteDes(hostDes); if (err!=KErrNone) { ret->error = FormatError("Host name lookup", err); LOGF(("sk_namelookup: RHostResolver.GetByName failed: %d, %s", err, ret->error)); delete ret->address; ret->address=NULL; hres.Close(); return ret; } namerec=nameres();#ifdef DEBUGLOG TBuf<40> buf; char buf8[41]; ((TInetAddr)namerec.iAddr).Output(buf); DesToString(buf, buf8); LOGF(("sk_namelookup: Resolved to %s", buf8));#endif *(ret->address) = (TInetAddr)namerec.iAddr; ret->family = ((TInetAddr)namerec.iAddr).Family(); err=hres.GetByAddress(namerec.iAddr,nameres); // Should compile as exedll project, or this fails on WINS... if ( err == KErrNone ) { namerec=nameres(); thehostname=namerec.iName; *canonicalname = (char *)smalloc(1+thehostname.Length()); DesToString(thehostname, *canonicalname); LOGF(("sk_namelookup: Reversed to %s", *canonicalname)); } else { // The call can often fail if the server has no valid reverse. This // happens, for example, if the name is a numeric address. *canonicalname = (char*) smalloc(strlen(host)+1); strcpy(*canonicalname, host); LOGF(("sk_namelookup: No reverse found")); } hres.Close(); return ret;}SockAddr sk_nonamelookup(const char *host){ SockAddr ret = snew(struct SockAddr_tag); ret->error = NULL; ret->family = KAFUnspec; ret->address = NULL; strncpy(ret->hostname, host, lenof(ret->hostname)); ret->hostname[lenof(ret->hostname)-1] = '\0'; return ret;}void sk_getaddr(SockAddr addr, char *buf, int buflen){ TBuf<40> ip; if ( addr->family == KAFUnspec ) { strncpy(buf, addr->hostname, buflen); buf[buflen-1] = '\0'; } else { addr->address->Output(ip); assert(buflen > ip.Length()); DesToString(ip, buf); }}int sk_hostname_is_local(char *name){ return !strcmp(name, "localhost");}int sk_address_is_local(SockAddr addr){#ifdef IPV6 return addr->address->IsLoopback();#else if (addr->family == KAfInet) { struct in_addr a; a.s_addr = htonl(addr->address->Address()); return ipv4_is_loopback(a); } else { return 0; }#endif}int sk_addrtype(SockAddr addr){ if ( addr->family == KAfInet ) return ADDRTYPE_IPV4;#ifdef IPV6 else if ( addr->family == KAfInet6 ) return ADDRTYPE_IPV6;#endif return ADDRTYPE_NAME;}void sk_addrcopy(SockAddr addr, char *buf){#ifdef IPV6 if ( addr->family == KAfInet6 ) { memcpy(buf, addr->address->Ip6Address().u.iAddr8, 16); return; }#endif TUint32 a = addr->address->Address(); TUint32 n = htonl(a); memcpy(buf, &n, 4);}void sk_addr_free(SockAddr addr){ if (addr->address) delete addr->address; sfree(addr);}static Plug sk_tcp_plug(Socket sock, Plug p){ Actual_Socket s = (Actual_Socket) sock; Plug ret = s->plug; if (p) s->plug = p; return ret;}static void sk_tcp_flush(Socket /*s*/){ /* * We send data to the socket as soon as we can anyway, * so we don't need to do anything here. :-) */}static void sk_tcp_close(Socket s);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -