00001
00002 Copyright (c) 2001, Lee Patterson & Ant Works Software
00003 http://ssobjects.sourceforge.net
00004
00005 Original source from Inside Visual C++
00006
00007 created : 5/14/1998
00008 filename : socketinstance.h
00009 author : Lee Patterson (lee@antws.com)
00010
00011 purpose : Base socket class. Also http and telnet
00012 classes. Defaults to blocking mode.
00013
00014 notes : Typical client session would look like this:
00015
00016 ...
00017 SocketInstance sConnection;
00018 try
00019 {
00020 //open connection
00021 puts("Connecting to server...");
00022 SockAddr saServer(szHost,iPort);
00023 if(isalpha(szHost[0])) //check if szHost is in "host.com" format or "255.255.255.255"
00024 saServer = SocketInstance::getHostByName(szHost,iPort);
00025 sConnection.create();
00026 sConnection.connect(saServer);
00027 //we are connected, so some transfering
00028 ...
00029 sConnection.close();
00030 }
00031 catch(GeneralException* e)
00032 {
00033 sConnection.cleanup();
00034 LOG("error %s",e->getErrorMsg());
00035 }
00036 ...
00037
00038 A server would look like this:
00039
00040 ...
00041 SocketInstance sClient;
00042 SockAddr saClient;
00043 SockAddr saServer(INADDR_ANY,atoi(argv[1]));
00044 SocketInstance sListen;
00045 try
00046 {
00047 sListen.create();
00048 sListen.bind(saServer);
00049 sListen.listen();
00050 while(bWantMoreConnections)
00051 {
00052 sListen.accept(sClient,saClient);
00053 //we got a connection ...
00054 sClient.close();
00055 }
00056 sListen.close();
00057 }
00058 catch(GeneralException* e)
00059 {
00060 sConnection.cleanup();
00061 LOG("error %s",e->getErrorMsg());
00062 }
00063 ...
00064
00065
00066
00067 *********************************************************************/
00068
00069 #ifndef SOCKETINSTANCE_H
00070 #define SOCKETINSTANCE_H
00071
00072 #ifdef OS_LINUX
00073 #define USE_POLL
00074 #endif
00075
00076 #define __SockAddr__
00077 #define __SocketInstance__
00078 #define __SocketInstanceException__
00079 #define __TelnetSocket__
00080 #define __HttpBlockingSocket__
00081
00082 #ifdef WIN32
00083 #include <winsock.h>
00084 #endif
00085
00086 #include <sys/types.h>
00087 #include <ctype.h>
00088 #include "msdefs.h"
00089 #include <stdio.h>
00090
00091 #ifndef WIN32
00092 # include <netinet/in.h>
00093 # include <netdb.h>
00094 # ifndef USE_POLL
00095 # include <sys/select.h>
00096 # else
00097 # include <sys/poll.h>
00098 # endif
00099 # include <arpa/inet.h>
00100 # include <sys/time.h>
00101 # include <sys/types.h>
00102 # include <sys/socket.h>
00103 # include <unistd.h>
00104 #endif
00105
00106 #include <stdio.h>
00107 #include <stdlib.h>
00108 #include "generalexception.h"
00109 #include "errno.h"
00110
00111 enum {
00112 DEFAULT_SOCKET_TIMEOUT=600,
00113 NO_TIMEOUT=0,
00114 };
00115
00116 #define TELNET_PORT 23
00117 #define WEB_PORT 80
00118
00119 #ifndef WIN32
00120 # define WSAEWOULDBLOCK EWOULDBLOCK
00121 # define SOCKET_ERROR (-1)
00122 # define INVALID_SOCKET (-1)
00123 # define closesocket(s) close(s)
00124 # define WSAGetLastError() errno
00125
00126 typedef int SOCKET;
00127 typedef struct sockaddr SOCKADDR;
00128
00129 typedef struct sockaddr_in SOCKADDR_IN;
00130 typedef struct sockaddr_in* LPSOCKADDR_IN;
00131 #endif
00132
00133 #ifdef WIN32
00134 typedef int socklen_t;
00135 #endif
00136
00137 typedef struct timeval TIMEVAL;
00138 typedef unsigned long ULONG;
00139 typedef unsigned short USHORT;
00140
00141 typedef const struct sockaddr* LPCSOCKADDR;
00142 typedef struct sockaddr* LPSOCKADDR;
00143
00144 namespace ssobjects
00145 {
00146
00147
00148
00149
00150
00151
00152 #ifdef __SocketInstanceException__
00153 #define throwSocketInstanceException(m) (throw SocketInstanceException(m,__FILE__,__LINE__))
00154
00161 class SocketInstanceException : public GeneralException
00162 {
00163 public:
00164 SocketInstanceException(const char* pchMessage,const char* pFname,const int iLine) : GeneralException(pchMessage,pFname,iLine){}
00165 ~SocketInstanceException(){}
00166 };
00167 #endif
00168
00169 #ifdef __SocketInstance__
00170 class SockAddr;
00171
00234 class SocketInstance
00235 {
00236 public:
00237 SOCKET m_hSocket;
00238 bool m_bThrowExceptionOnReadClose;
00239 SocketInstance() : m_hSocket(0),m_bThrowExceptionOnReadClose(true) {}
00240 SOCKET getSocket() const {return m_hSocket;}
00241 void setExceptionOnReadClose(const bool bThrowException=true);
00242 void cleanup();
00243 void create(const int nType = SOCK_STREAM);
00244 void close();
00245 void bind(LPCSOCKADDR psa);
00246 void listen();
00247 void connect(LPCSOCKADDR psa);
00248 bool accept(SocketInstance& s, LPSOCKADDR psa);
00249 bool accept(SocketInstance* s, LPSOCKADDR psa);
00250 int send(const char* pch, const int nSize, const int nSecs=DEFAULT_SOCKET_TIMEOUT);
00251 int write(const char* pch, const int nSize, const int nSecs=DEFAULT_SOCKET_TIMEOUT);
00252 int recv(char* pch, const int nSize, const int nSecs=DEFAULT_SOCKET_TIMEOUT);
00253 int sendDatagram(const char* pch, const int nSize, LPCSOCKADDR psa,
00254 const int nSecs=10);
00255 int receiveDatagram(char* pch, const int nSize, LPSOCKADDR psa,
00256 const int nSecs=10);
00257 void getPeerAddr(LPSOCKADDR psa);
00258 void getSockAddr(LPSOCKADDR psa);
00259 static SockAddr getHostByName(const char* pchName,
00260 const USHORT ushPort = 0);
00261 static const char* getHostByAddr(LPCSOCKADDR psa);
00262 operator SOCKET()
00263 { return m_hSocket; }
00264
00265 SocketInstance& operator=(const SocketInstance& s);
00266 SocketInstance(const SocketInstance& s) : m_hSocket(s.m_hSocket),m_bThrowExceptionOnReadClose(s.m_bThrowExceptionOnReadClose) {}
00267 };
00268 #endif
00269
00270 #ifdef __SockAddr__
00271
00277 class SockAddr : public sockaddr_in
00278 {
00279 public:
00280
00281 SockAddr()
00282 { sin_family = AF_INET;
00283 sin_port = 0;
00284 sin_addr.s_addr = 0; }
00285 SockAddr(const sockaddr& sa) { memcpy(this, &sa, sizeof(SOCKADDR)); }
00286 SockAddr(const sockaddr_in& sin) { memcpy(this, &sin, sizeof(SOCKADDR_IN)); }
00287 SockAddr(const ULONG ulAddr, const USHORT ushPort = 0)
00288 { sin_family = AF_INET;
00289 sin_port = htons(ushPort);
00290 sin_addr.s_addr = htonl(ulAddr); }
00291 #ifdef OS_LINUX
00292 SockAddr(const uint32_t ulAddr, const USHORT ushPort = 0)
00293 { sin_family = AF_INET;
00294 sin_port = htons(ushPort);
00295 sin_addr.s_addr = htonl(ulAddr); }
00296 #endif
00297 SockAddr(const char* pchIP, const USHORT ushPort = 0)
00298 {
00299 if(isalpha(pchIP[0]))
00300 {
00301 struct hostent* pHostEnt = gethostbyname(pchIP);
00302 if(pHostEnt == NULL) {
00303 CStr s;
00304 int err = WSAGetLastError();
00305 strerror(err);
00306 s.format("SockAddr GetHostByName error %d:%s",err,strerror(err));
00307
00308 throwSocketInstanceException((const char*)s);
00309 }
00310 ULONG* pulAddr = (ULONG*) pHostEnt->h_addr_list[0];
00311 sin_family = AF_INET;
00312 sin_port = htons(ushPort);
00313 sin_addr.s_addr = *pulAddr;
00314
00315 }
00316 else
00317 {
00318 sin_family = AF_INET;
00319 sin_port = htons(ushPort);
00320 sin_addr.s_addr = inet_addr(pchIP);
00321 }
00322 }
00323
00324 char* dottedDecimal()
00325 { return inet_ntoa(sin_addr); }
00326
00327 USHORT port() const
00328 { return ntohs(sin_port); }
00329 ULONG ipAddr() const
00330 { return ntohl(sin_addr.s_addr); }
00331
00332 const SockAddr& operator=(const SOCKADDR& sa)
00333 { memcpy(this, &sa, sizeof(SOCKADDR));
00334 return *this; }
00335 const SockAddr& operator=(const SOCKADDR_IN& sin)
00336 { memcpy(this, &sin, sizeof(SOCKADDR_IN));
00337 return *this; }
00338 operator SOCKADDR()
00339 { return *((LPSOCKADDR) this); }
00340 operator LPSOCKADDR()
00341 { return (LPSOCKADDR) this; }
00342 operator LPSOCKADDR_IN()
00343 { return (LPSOCKADDR_IN) this; }
00344 bool operator == (const sockaddr_in& sa);
00345 };
00346 #endif
00347
00348
00349 #ifdef __TelnetSocket__
00350 class TelnetSocket : public SocketInstance
00351 {
00352 public:
00353 enum {nSizeRecv = 1024};
00354 enum {FLAG_VALIDATED=1,FLAG_PLAYING=2};
00355 TelnetSocket();
00356 TelnetSocket(SocketInstance& s);
00357 TelnetSocket(SocketInstance* s);
00358 virtual ~TelnetSocket();
00359 int readLine(char* pch, const int nSize, const int nSecs=DEFAULT_SOCKET_TIMEOUT);
00360 int readResponse(char* pch, const int nSize, const int nSecs=DEFAULT_SOCKET_TIMEOUT);
00361 int println(const char* fmt,...);
00362 int print(const char* fmt,...);
00363 bool setLoginName(const char* name);
00364
00365 public:
00366
00367 char* m_pLoginName;
00368 WORD m_wFlags;
00369
00370 private:
00371 char* m_pReadBuf;
00372 int m_nReadBuf;
00373
00374 private:
00375 TelnetSocket(const TelnetSocket&);
00376 TelnetSocket& operator=(const TelnetSocket&);
00377 };
00378 #endif
00379
00380 #ifdef __HttpBlockingSocket__
00381 class HttpBlockingSocket : public SocketInstance
00382 {
00383 public:
00384 enum {nSizeRecv = 1000};
00385 HttpBlockingSocket();
00386 ~HttpBlockingSocket();
00387 int readHttpHeaderLine(char* pch, const int nSize, const int nSecs);
00388 int readHttpResponse(char* pch, const int nSize, const int nSecs);
00389 private:
00390 char* m_pReadBuf;
00391 int m_nReadBuf;
00392 private:
00393
00394 HttpBlockingSocket(const HttpBlockingSocket&);
00395 HttpBlockingSocket& operator=(const HttpBlockingSocket&);
00396 };
00397 #endif
00398
00399 };
00400
00401 #endif
00402