00001 /* 00002 This file is part of the Virtual Object System of 00003 the Interreality project (http://interreality.org). 00004 00005 Copyright (C) 2001-2003 Peter Amstutz 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Lesser General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Lesser General Public License for more details. 00016 00017 You should have received a copy of the GNU Lesser General Public 00018 License along with this library; if not, write to the Free Software 00019 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00020 00021 Peter Amstutz <tetron@interreality.org> 00022 */ 00023 #ifndef _LOCALSOCKETSITE_HH_ 00024 #define _LOCALSOCKETSITE_HH_ 00025 00026 /** @file 00027 Defines LocalSite. 00028 */ 00029 00030 #include <vos/corelibs/vos/vosdefs.hh> 00031 #include <vos/corelibs/vos/localsite.hh> 00032 #include <stdexcept> 00033 00034 namespace VOS 00035 { 00036 class SiteAccessControl; 00037 00038 /** @class LocalSocketSite localsocketsite.hh vos/corelibs/vos/localsocketsite.hh 00039 * 00040 * A local site implemented using TCP sockets. It binds a TCP socket 00041 and accepts connection requests. 00042 */ 00043 class VOS_API LocalSocketSite : public virtual LocalSite 00044 { 00045 public: 00046 /** An exception class thrown when there is an error initializing the listening socket */ 00047 class PortBindingError : public runtime_error { 00048 public: 00049 PortBindingError(const string& s) : runtime_error(s) { } 00050 }; 00051 /** An exception class thrown when there is an error initializing SSL */ 00052 class SSLError : public runtime_error { 00053 public: 00054 SSLError(const string& s) : runtime_error(s) { }; 00055 }; 00056 00057 private: 00058 int listensocket; 00059 unsigned short int listenport; 00060 bool alreadyDoingFlushIncoming; 00061 bool usingSOCKS; 00062 00063 SSL_CTX* TLSv1context; 00064 SSL_CTX* SSLv3context; 00065 00066 map<int, pair<int, int> > extra_fds; 00067 00068 void init(const string& defaultHostname, unsigned short int port) throw (PortBindingError); 00069 void acceptConnectionRequests(); 00070 static int pemPasswordCallback(char *buf, int size, int rwflag, void *password); 00071 static int sslVerifyCallback(int preverify_ok, X509_STORE_CTX *ctx); 00072 00073 public: 00074 /** The usual constructor to use. Gets hostname from the system (gethostname), unless 00075 * "VOS_HOSTNAME" environment variable is present. 00076 * Uses the first free port number <= 4231 (VOS_DEFAULT_PORT) 00077 */ 00078 LocalSocketSite(SiteAccessControl* ac) throw (PortBindingError); 00079 00080 LocalSocketSite(const string& defaultHostname, unsigned short int port, SiteAccessControl* ac) throw (PortBindingError); 00081 LocalSocketSite(const string& defaultHostname, SiteAccessControl* ac) throw (PortBindingError); 00082 LocalSocketSite(unsigned short int port, SiteAccessControl* ac) throw (PortBindingError); 00083 00084 //LocalSite() throw (PortBindingError); 00085 /** destructor */ 00086 virtual ~LocalSocketSite(); 00087 00088 virtual void flushIncomingBuffers(); 00089 00090 /** Calculate the timeout value of the next call to select() and 00091 return an appropriate timeval structure. If the time returned 00092 is less than the time set with setTimeoutOnSelect(), then it 00093 is amount of time to the next event (message delivery or timer 00094 callback). If a null pointer is returned, the select is 00095 expected to block indefinitely. 00096 @return a pointer timeval structure allocated with 'new', 00097 which the user is expected to 'delete' when done; or may be 00098 null signifying an indefinitely wait. 00099 */ 00100 struct timeval* calculateTimeout(); 00101 00102 /** On the supplied file descriptor sets, set all the file 00103 descriptors that a call to flushIncomingBuffers() would wait 00104 upon. 00105 @param readset the FDs to wait for reading 00106 @param writeset the FDs to wait for writing 00107 @param errorset the FDs to wait for errors 00108 @return the largest value file descriptor that was set 00109 */ 00110 int getFDset(fd_set* readset, fd_set* writeset, fd_set* errorset); 00111 00112 static const int SELECTREAD; 00113 static const int SELECTWRITE; 00114 static const int SELECTERROR; 00115 00116 /** Add an extra file descriptor to our select() call. 00117 @param fd the file description 00118 @param which The OR'd together flags of 00119 LocalSocketSite::SELECTREAD, LocalSocketSite::SELECTWRITE and 00120 LocalSocketSite::SELECTERROR specifying which select set to 00121 add the file descriptor to. 00122 */ 00123 void addFDtoSelect(int fd, int which); 00124 00125 /** Remove an extra file descriptor to our select() call. 00126 @param fd the file description 00127 @param which The OR'd together flags of 00128 LocalSocketSite::SELECTREAD, LocalSocketSite::SELECTWRITE and 00129 LocalSocketSite::SELECTERROR specifying which select set to 00130 remove the file descriptor from. 00131 */ 00132 void removeFDfromSelect(int fd, int which); 00133 00134 /** Get most recent result for this file descriptor. 00135 @param fd the file description 00136 @return The result stored in the first three bits. Do a 00137 boolean AND to get the result for each select set. For example: 00138 @code 00139 x = lastSelectResultForFD(fd); 00140 if(x & LocalSocketSite::SELECTREAD) ... 00141 @endcode 00142 */ 00143 int lastSelectResultForFD(int fd); 00144 00145 virtual void sendMessage(Message* m); 00146 00147 /** Get the OpenSSL context. Will return NULL if there was an 00148 error or VOS was not compiled with SSL support. 00149 */ 00150 SSL_CTX* getSSLContext(const string& protocol); 00151 00152 /** Set up our SSL identity. 00153 @param certificateFile The filename the X509 certificate (public key) 00154 @param privateKeyFile The filename the private key 00155 @param password The password needed to decrypt the private key file 00156 */ 00157 void setupSSL(const string& certificateFile, const string& privateKeyFile, const string& password); 00158 00159 friend void Site::doSitePeering(LocalSite* localsite, RemoteSite* remotesite, bool isspooftest, bool waitforhello); 00160 00161 /** Return the underlying system socket file descriptor on which 00162 this site is listening. You are strongly advised NOT to read 00163 or write to this file descriptor, but you may find it rather 00164 useful to know for doing your own select() calls... */ 00165 int getSocket() { 00166 return listensocket; 00167 } 00168 }; 00169 } 00170 00171 #endif