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