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