Make WvStreams compile with gcc 4.4.
[wvstreams.git] / ipstreams / wvunixdgsocket.cc
blob41d2911f71ffd81995826811fc360b320ac4f95d
1 #include "wvunixdgsocket.h"
2 #ifdef MACOS
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #endif
7 WvUnixDGSocket::WvUnixDGSocket(WvStringParm filename, bool _server, int perms)
8 : socketfile(filename)
10 // log(WvLog::Debug2, "Starting up %s!\n", filename);
11 server = _server;
12 backoff = 10;
14 bufsize = 0;
16 // open a datagram unix domain socket
17 setfd(socket(PF_UNIX, SOCK_DGRAM, 0));
19 // if we don't have a file desciptor, something is wrong.
20 if (getfd() < 0)
22 seterr("No Socket available.");
23 return;
26 // set non-blocking mode
27 fcntl(getfd(), F_SETFL, O_RDWR|O_NONBLOCK);
29 WvUnixAddr uaddr(socketfile);
31 // Let this file be reusable, since we're going to own this anyway
32 // The business with the int x is just Unix stupidities.. *sigh*
33 int x = 1;
34 setsockopt(getfd(), SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
36 if (server)
38 // Fix it so that there can't be another process on this file
39 unlink(socketfile);
41 // Actually bind to the address we set up above.
42 sockaddr *addr = uaddr.sockaddr();
43 if (bind(getfd(), (sockaddr *)addr, uaddr.sockaddr_len()))
45 seterr("Bind to %s failed: %s", socketfile, strerror(errno));
46 close();
48 delete addr;
50 chmod(socketfile, perms);
52 else
54 // we're the client, so we connect to someone else's socket
55 sockaddr *addr = uaddr.sockaddr();
56 if (connect(getfd(), (sockaddr *)addr, uaddr.sockaddr_len()))
58 seterr("Connect to %s failed: %s",
59 socketfile, strerror(errno));
60 close();
62 delete addr;
65 drain();
68 WvUnixDGSocket::~WvUnixDGSocket()
70 // log(WvLog::Debug2, "Destroying: %s\n", socketfile);
71 close();
72 if (server)
73 unlink(socketfile);
76 size_t WvUnixDGSocket::uwrite(const void *buf, size_t count)
78 size_t ret = bufs.isempty() ? WvFDStream::uwrite(buf, count) : 0;
80 if (ret < count)
82 WvDynBuf *b = new WvDynBuf;
83 b->put(buf, count);
84 bufs.append(b, true);
85 bufsize += count;
88 return count;
91 void WvUnixDGSocket::pre_select(SelectInfo &si)
93 SelectRequest oldwant = si.wants;
94 if (!bufs.isempty())
96 // stupid unix domain sockets seem to return true when selecting
97 // for write EVEN IF write() RETURNS -EAGAIN! Just shoot me.
98 //
99 // To deal with this, we set an alarm() in post_select() if we
100 // couldn't write everything we wanted. While the alarm is set,
101 // we don't try to flush our output buffer.
102 if (alarm_remaining() <= 0)
103 si.wants.writable = true;
104 else if (si.msec_timeout < 0
105 || si.msec_timeout > alarm_remaining())
106 si.msec_timeout = alarm_remaining();
109 WvFDStream::pre_select(si);
111 si.wants = oldwant;
114 bool WvUnixDGSocket::post_select(SelectInfo &si)
116 SelectRequest oldwant = si.wants;
117 if (!bufs.isempty())
118 si.wants.writable = true;
120 bool sure = WvFDStream::post_select(si);
122 si.wants = oldwant;
124 if (sure)
126 // try flushing previous bufs
127 WvBufList::Iter i(bufs);
128 for (i.rewind(); i.next(); )
130 int used = i->used();
131 int retval = WvFDStream::uwrite(i->get(used), used);
132 if (retval < used)
134 i->unget(used);
135 alarm(backoff *= 2);
136 if (backoff > 1000)
137 backoff = 1000;
138 break; // can't continue
140 else
142 bufsize -= used;
143 i.xunlink(); // done with that one
144 backoff = 10;
149 return sure;