WvStreams
wvunixdgsocket.cc
1#include "wvunixdgsocket.h"
2#ifdef MACOS
3#include <sys/types.h>
4#include <sys/stat.h>
5#endif
6
7WvUnixDGSocket::WvUnixDGSocket(WvStringParm filename, bool _server, int perms)
8 : socketfile(filename)
9{
10// log(WvLog::Debug2, "Starting up %s!\n", filename);
11 server = _server;
12 backoff = 10;
13
14 bufsize = 0;
15
16 // open a datagram unix domain socket
17 setfd(socket(PF_UNIX, SOCK_DGRAM, 0));
18
19 // if we don't have a file desciptor, something is wrong.
20 if (getfd() < 0)
21 {
22 seterr("No Socket available.");
23 return;
24 }
25
26 // set non-blocking mode
27 fcntl(getfd(), F_SETFL, O_RDWR|O_NONBLOCK);
28
29 WvUnixAddr uaddr(socketfile);
30
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));
35
36 if (server)
37 {
38 // Fix it so that there can't be another process on this file
39 unlink(socketfile);
40
41 // Actually bind to the address we set up above.
42 sockaddr *addr = uaddr.sockaddr();
43 if (bind(getfd(), (sockaddr *)addr, uaddr.sockaddr_len()))
44 {
45 seterr("Bind to %s failed: %s", socketfile, strerror(errno));
46 close();
47 }
48 delete addr;
49
50 chmod(socketfile, perms);
51 }
52 else
53 {
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()))
57 {
58 seterr("Connect to %s failed: %s",
59 socketfile, strerror(errno));
60 close();
61 }
62 delete addr;
63 }
64
65 drain();
66}
67
68WvUnixDGSocket::~WvUnixDGSocket()
69{
70// log(WvLog::Debug2, "Destroying: %s\n", socketfile);
71 close();
72 if (server)
73 unlink(socketfile);
74}
75
76size_t WvUnixDGSocket::uwrite(const void *buf, size_t count)
77{
78 size_t ret = bufs.isempty() ? WvFDStream::uwrite(buf, count) : 0;
79
80 if (ret < count)
81 {
82 WvDynBuf *b = new WvDynBuf;
83 b->put(buf, count);
84 bufs.append(b, true);
85 bufsize += count;
86 }
87
88 return count;
89}
90
92{
93 SelectRequest oldwant = si.wants;
94 if (!bufs.isempty())
95 {
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();
107 }
108
110
111 si.wants = oldwant;
112}
113
115{
116 SelectRequest oldwant = si.wants;
117 if (!bufs.isempty())
118 si.wants.writable = true;
119
120 bool sure = WvFDStream::post_select(si);
121
122 si.wants = oldwant;
123
124 if (sure)
125 {
126 // try flushing previous bufs
127 WvBufList::Iter i(bufs);
128 for (i.rewind(); i.next(); )
129 {
130 int used = i->used();
131 int retval = WvFDStream::uwrite(i->get(used), used);
132 if (retval < used)
133 {
134 i->unget(used);
135 alarm(backoff *= 2);
136 if (backoff > 1000)
137 backoff = 1000;
138 break; // can't continue
139 }
140 else
141 {
142 bufsize -= used;
143 i.xunlink(); // done with that one
144 backoff = 10;
145 }
146 }
147 }
148
149 return sure;
150}
151
152
void put(const T *data, size_t count)
Writes the specified number of elements from the specified storage location into the buffer at its ta...
Definition wvbufbase.h:483
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
Definition wvstring.h:94
virtual void close()
Closes the file descriptors.
virtual bool post_select(SelectInfo &si)
post_select() is called after select(), and returns true if this object is now ready.
virtual void pre_select(SelectInfo &si)
pre_select() sets up for eventually calling select().
virtual size_t uwrite(const void *buf, size_t count)
unbuffered I/O functions; these ignore the buffer, which is handled by write().
void alarm(time_t msec_timeout)
set an alarm, ie.
Definition wvstream.cc:1048
time_t alarm_remaining()
return the number of milliseconds remaining before the alarm will go off; -1 means no alarm is set (i...
Definition wvstream.cc:1057
A Unix domain socket address is really just a filename.
Definition wvaddr.h:430
virtual size_t uwrite(const void *buf, size_t count)
unbuffered I/O functions; these ignore the buffer, which is handled by write().
virtual bool post_select(SelectInfo &si)
post_select() is called after select(), and returns true if this object is now ready.
virtual void pre_select(SelectInfo &si)
pre_select() sets up for eventually calling select().
the data structure used by pre_select()/post_select() and internally by select().
Definition iwvstream.h:50
A SelectRequest is a convenient way to remember what we want to do to a particular stream: read from ...
Definition iwvstream.h:34