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