00001 #include "wvunixdgsocket.h"
00002 #include <sys/types.h>
00003 #include <sys/stat.h>
00004
00005 WvUnixDGSocket::WvUnixDGSocket(WvStringParm filename, bool _server, int perms)
00006 : socketfile(filename)
00007 {
00008
00009 server = _server;
00010 backoff = 10;
00011
00012 bufsize = 0;
00013
00014
00015 setfd(socket(PF_UNIX, SOCK_DGRAM, 0));
00016
00017
00018 if (getfd() < 0)
00019 {
00020 seterr("No Socket available.");
00021 return;
00022 }
00023
00024
00025 fcntl(getfd(), F_SETFL, O_RDWR|O_NONBLOCK);
00026
00027 WvUnixAddr uaddr(socketfile);
00028
00029
00030
00031 int x = 1;
00032 setsockopt(getfd(), SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
00033
00034 if (server)
00035 {
00036
00037 unlink(socketfile);
00038
00039
00040 sockaddr *addr = uaddr.sockaddr();
00041 if (bind(getfd(), (sockaddr *)addr, uaddr.sockaddr_len()))
00042 {
00043 seterr("Bind to %s failed: %s", socketfile, strerror(errno));
00044 close();
00045 }
00046 delete addr;
00047
00048 chmod(socketfile, perms);
00049 }
00050 else
00051 {
00052
00053 sockaddr *addr = uaddr.sockaddr();
00054 if (connect(getfd(), (sockaddr *)addr, uaddr.sockaddr_len()))
00055 {
00056 seterr("Connect to %s failed: %s",
00057 socketfile, strerror(errno));
00058 close();
00059 }
00060 delete addr;
00061 }
00062
00063 drain();
00064 }
00065
00066 WvUnixDGSocket::~WvUnixDGSocket()
00067 {
00068
00069 close();
00070 if (server)
00071 unlink(socketfile);
00072 }
00073
00074 size_t WvUnixDGSocket::uwrite(const void *buf, size_t count)
00075 {
00076 size_t ret = bufs.isempty() ? WvFDStream::uwrite(buf, count) : 0;
00077
00078 if (ret < count)
00079 {
00080 WvDynBuf *b = new WvDynBuf;
00081 b->put(buf, count);
00082 bufs.append(b, true);
00083 bufsize += count;
00084 }
00085
00086 return count;
00087 }
00088
00089 void WvUnixDGSocket::pre_select(SelectInfo &si)
00090 {
00091 SelectRequest oldwant = si.wants;
00092 if (!bufs.isempty())
00093 {
00094
00095
00096
00097
00098
00099
00100 if (alarm_remaining() <= 0)
00101 si.wants.writable = true;
00102 else if (si.msec_timeout < 0
00103 || si.msec_timeout > alarm_remaining())
00104 si.msec_timeout = alarm_remaining();
00105 }
00106
00107 WvFDStream::pre_select(si);
00108
00109 si.wants = oldwant;
00110 }
00111
00112 bool WvUnixDGSocket::post_select(SelectInfo &si)
00113 {
00114 SelectRequest oldwant = si.wants;
00115 if (!bufs.isempty())
00116 si.wants.writable = true;
00117
00118 bool sure = WvFDStream::post_select(si);
00119
00120 si.wants = oldwant;
00121
00122 if (sure)
00123 {
00124
00125 WvBufList::Iter i(bufs);
00126 for (i.rewind(); i.next(); )
00127 {
00128 int used = i->used();
00129 int retval = WvFDStream::uwrite(i->get(used), used);
00130 if (retval < used)
00131 {
00132 i->unget(used);
00133 alarm(backoff *= 2);
00134 if (backoff > 1000)
00135 backoff = 1000;
00136 break;
00137 }
00138 else
00139 {
00140 bufsize -= used;
00141 i.xunlink();
00142 backoff = 10;
00143 }
00144 }
00145 }
00146
00147 return sure;
00148 }
00149
00150