summaryrefslogtreecommitdiff
path: root/lib/server/SocketStream.h
blob: 6b029387d7d869a496b5d0889052e8ca9fdabf13 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// --------------------------------------------------------------------------
//
// File
//		Name:    SocketStream.h
//		Purpose: I/O stream interface for sockets
//		Created: 2003/07/31
//
// --------------------------------------------------------------------------

#ifndef SOCKETSTREAM__H
#define SOCKETSTREAM__H

#include <climits>

#ifdef HAVE_SYS_POLL_H
#	include <sys/poll.h>
#endif

#include "BoxTime.h"
#include "IOStream.h"
#include "Socket.h"

#ifdef WIN32
	typedef SOCKET tOSSocketHandle;
	#define INVALID_SOCKET_VALUE (tOSSocketHandle)(-1)
#else
	typedef int tOSSocketHandle;
	#define INVALID_SOCKET_VALUE -1
#endif

// --------------------------------------------------------------------------
//
// Class
//		Name:    SocketStream
//		Purpose: Stream interface for sockets
//		Created: 2003/07/31
//
// --------------------------------------------------------------------------
class SocketStream : public IOStream
{
public:
	SocketStream();
	SocketStream(int socket);
	SocketStream(const SocketStream &rToCopy);
	~SocketStream();
	
	void Open(Socket::Type Type, const std::string& rName, int Port = 0);
	void Attach(int socket);

	virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite);
	virtual void Write(const void *pBuffer, int NBytes,
		int Timeout = IOStream::TimeOutInfinite);

	// Why not inherited from IOStream? Never mind, we want to enforce
	// supplying a timeout for network operations anyway.
	virtual void Write(const std::string& rBuffer, int Timeout)
	{
		IOStream::Write(rBuffer, Timeout);
	}

	virtual void Close();
	virtual bool StreamDataLeft();
	virtual bool StreamClosed();

	virtual void Shutdown(bool Read = true, bool Write = true);

	virtual bool GetPeerCredentials(uid_t &rUidOut, gid_t &rGidOut);

protected:
	void MarkAsReadClosed() {mReadClosed = true;}
	void MarkAsWriteClosed() {mWriteClosed = true;}
	void CheckForMissingTimeout(int Timeout);

	// Converts a timeout in milliseconds (or IOStream::TimeOutInfinite)
	// into one that can be passed to poll() (also in milliseconds), also
	// compensating for time elapsed since the wait should have started,
	// if known.
	int PollTimeout(int timeout, box_time_t start_time)
	{
		if (timeout == IOStream::TimeOutInfinite)
		{
			return INFTIM;
		}

		if (start_time == 0)
		{
			return timeout; // no adjustment possible
		}

		box_time_t end_time = start_time + MilliSecondsToBoxTime(timeout);
		box_time_t now = GetCurrentBoxTime();
		box_time_t remaining = end_time - now;

		if (remaining < 0)
		{
			return 0; // no delay
		}
		else if (BoxTimeToMilliSeconds(remaining) > INT_MAX)
		{
			return INT_MAX;
		}
		else
		{
			return (int) BoxTimeToMilliSeconds(remaining);
		}
	}
	bool Poll(short Events, int Timeout);

private:
	tOSSocketHandle mSocketHandle;
	bool mReadClosed;
	bool mWriteClosed;

protected:
	off_t mBytesRead;
	off_t mBytesWritten;
	std::string mPeerSocketDesc;

public:
	off_t GetBytesRead() const {return mBytesRead;}
	off_t GetBytesWritten() const {return mBytesWritten;}
	void ResetCounters() {mBytesRead = mBytesWritten = 0;}
	bool IsOpened() { return mSocketHandle != INVALID_SOCKET_VALUE; }
	
	/**
	 * Only for use by NiceSocketStream!
	 */
	tOSSocketHandle GetSocketHandle();
};

#endif // SOCKETSTREAM__H