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 Sat Mar 13 14:56:01 2004 for WvStreams by doxygen 1.3.6-20040222