Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

wvunixsocket.cc

Go to the documentation of this file.
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * WvStream-based Unix domain socket connection class. See wvunixsocket.h. 00006 */ 00007 #include "wvstreamlist.h" 00008 #include "wvunixsocket.h" 00009 #include "wvmoniker.h" 00010 00011 #if 0 00012 // FIXME: this is needed on BSD 00013 #include <netinet/in_systm.h> 00014 #endif 00015 00016 #ifdef ISDARWIN 00017 #define socklen_t int 00018 #endif 00019 00020 #include <fcntl.h> 00021 #include <sys/socket.h> 00022 #include <sys/stat.h> 00023 #include <sys/types.h> 00024 #include <sys/un.h> 00025 #include <netinet/in.h> 00026 #include <netinet/ip.h> 00027 #include <netinet/tcp.h> 00028 #include <errno.h> 00029 00030 00031 static IWvStream *creator(WvStringParm s, IObject *, void *) 00032 { 00033 return new WvUnixConn(s); 00034 } 00035 00036 static WvMoniker<IWvStream> reg("unix", creator); 00037 00038 00039 WvUnixConn::WvUnixConn(int _fd, const WvUnixAddr &_addr) : 00040 WvFDStream(_fd), addr(_addr) 00041 { 00042 // all is well and we're connected. Make it non-blocking 00043 // and close-on-exec. 00044 fcntl(getfd(), F_SETFD, FD_CLOEXEC); 00045 fcntl(getfd(), F_SETFL, O_RDWR|O_NONBLOCK); 00046 } 00047 00048 00049 WvUnixConn::WvUnixConn(const WvUnixAddr &_addr) : 00050 addr(_addr) 00051 { 00052 setfd(socket(PF_UNIX, SOCK_STREAM, 0)); 00053 if (getfd() < 0) 00054 { 00055 seterr(errno); 00056 return; 00057 } 00058 00059 sockaddr *sa = addr.sockaddr(); 00060 if (connect(getfd(), sa, addr.sockaddr_len()) < 0) 00061 { 00062 seterr(errno); 00063 delete sa; 00064 return; 00065 } 00066 00067 delete sa; 00068 00069 // all is well and we're connected. Make it non-blocking 00070 // and close-on-exec. 00071 fcntl(getfd(), F_SETFD, FD_CLOEXEC); 00072 fcntl(getfd(), F_SETFL, O_RDWR|O_NONBLOCK); 00073 } 00074 00075 00076 WvUnixConn::~WvUnixConn() 00077 { 00078 // we don't want to delete the socket file here; that's a job for the 00079 // listener class. 00080 00081 // close the socket 00082 close(); 00083 } 00084 00085 00086 const WvUnixAddr *WvUnixConn::src() const 00087 { 00088 return &addr; 00089 } 00090 00091 00092 WvUnixListener::WvUnixListener(const WvUnixAddr &_addr, int create_mode) 00093 : addr(_addr) 00094 { 00095 mode_t oldmask; 00096 00097 auto_list = NULL; 00098 auto_userdata = NULL; 00099 bound_okay = false; 00100 00101 sockaddr *sa = addr.sockaddr(); 00102 00103 // unfortunately we have to change the umask here to make the create_mode 00104 // work, because bind() doesn't take extra arguments like open() does. 00105 // However, we don't actually want to _cancel_ the effects of umask, 00106 // only add to them; so the original umask is or'ed into ~create_mode. 00107 oldmask = umask(0777); // really just reading the old umask here 00108 umask(oldmask | ((~create_mode) & 0777)); 00109 00110 setfd(socket(PF_UNIX, SOCK_STREAM, 0)); 00111 if (getfd() < 0 00112 || fcntl(getfd(), F_SETFD, 1) 00113 || bind(getfd(), sa, addr.sockaddr_len()) 00114 || listen(getfd(), 5)) 00115 { 00116 seterr(errno); 00117 } 00118 else 00119 bound_okay = true; 00120 00121 delete sa; 00122 umask(oldmask); 00123 } 00124 00125 00126 WvUnixListener::~WvUnixListener() 00127 { 00128 close(); 00129 } 00130 00131 00132 void WvUnixListener::close() 00133 { 00134 // delete the socket _before_ closing it. Unix will keep 00135 // existing connections around anyway (if any), but if it's idle, then 00136 // we never have an existing not-in-use socket inode. 00137 if (bound_okay) 00138 { 00139 WvString filename(addr); 00140 ::unlink(filename); 00141 } 00142 00143 WvFDStream::close(); 00144 } 00145 00146 00147 WvUnixConn *WvUnixListener::accept() 00148 { 00149 struct sockaddr_un sun; 00150 socklen_t len = sizeof(sun); 00151 int newfd; 00152 WvUnixConn *ret; 00153 00154 newfd = ::accept(getfd(), (struct sockaddr *)&sun, &len); 00155 ret = new WvUnixConn(newfd, addr); 00156 return ret; 00157 } 00158 00159 00160 void WvUnixListener::auto_accept(WvStreamList *list, 00161 WvStreamCallback callfunc, void *userdata) 00162 { 00163 auto_list = list; 00164 auto_callback = callfunc; 00165 auto_userdata = userdata; 00166 setcallback(accept_callback, this); 00167 } 00168 00169 00170 void WvUnixListener::accept_callback(WvStream &, void *userdata) 00171 { 00172 WvUnixListener &l = *(WvUnixListener *)userdata; 00173 00174 WvUnixConn *connection = l.accept(); 00175 connection->setcallback(l.auto_callback, l.auto_userdata); 00176 l.auto_list->append(connection, true); 00177 } 00178 00179 00180 size_t WvUnixListener::uread(void *, size_t) 00181 { 00182 return 0; 00183 } 00184 00185 00186 size_t WvUnixListener::uwrite(const void *, size_t) 00187 { 00188 return 0; 00189 } 00190 00191 00192 const WvUnixAddr *WvUnixListener::src() const 00193 { 00194 return &addr; 00195 } 00196

Generated on Tue Oct 5 01:09:21 2004 for WvStreams by doxygen 1.3.7