My favorites | Sign in
Project Home Downloads Source
Checkout   Browse   Changes    
 
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
//#define NOFAKEERROR

static const int DEFAULT_CONNECT_TIMEOUT = 5000;

static const int SOCKKIND_STD = 1; // GetKind() for ordinary socket

class Socket : Moveable<Socket>
{
public:
class Data
{
public:
Data();
virtual ~Data() { CloseRaw(0); }

bool Open(bool is_blocking);
bool OpenServer(int port, bool nodelay, int listen_count, bool is_blocking, bool reuse = true);
bool OpenClient(const char *host, int port, bool nodelay, dword *my_addr, int timeout, bool is_blocking);
bool IsOpen() const { return socket != INVALID_SOCKET; }
bool CloseRaw(int timeout_msec);

bool IsEof() const { return is_eof && leftover.IsEmpty(); }
bool IsError() const { return sock && sock->IsError(); }
void ClearError() { if(sock) sock->ClearError(); }

void NoDelay();
void Linger(int msecs);
void Block(bool b = true);
// void WriteTimeout(int msecs);
// void ReadTimeout(int msecs);
void StopWrite();

String GetPeerAddr() const;

virtual int GetKind() const { return SOCKKIND_STD; }

virtual bool Peek(int timeout_msec, bool write);
virtual int Read(void *buf, int amount);
virtual int Write(const void *buf, int amount);
virtual bool Accept(Socket& socket, dword *ipaddr, bool nodelay, int timeout_msec);
virtual bool Close(int timeout_msec);
virtual Value GetInfo(String info) const;

public:
Socket *sock;
SOCKET socket;
String leftover;
bool is_blocking;
// bool is_error;
bool is_eof;
#ifndef NOFAKEERROR
int fake_error;
#endif

protected:
SOCKET AcceptRaw(dword *ipaddr, int timeout_msec);
void Attach(SOCKET socket, bool nodelay, bool is_blocking);
void SetSockResError(const String& context);
void AttachRaw(SOCKET s, bool blocking);
void SetSockError(const String& context);
void SetSockError(const String& context, int code, const String& errortext);

friend void AttachSocket(Socket& socket, SOCKET hsocket, bool blocking);
};

Socket() { ClearError(); }
Socket(One<Data> data) : data(data) { ClearError(); if(data) data->sock = this; }
Socket(pick_ Socket& s) : data(s.data) { ClearError(); if(data) data->sock = this; }

Socket& operator = (pick_ Socket& s) { ClearError(); data = s.data; if(data) data->sock = this; return *this; }

static void Init();

void Attach(One<Data> d) { data = d; data->sock = this; ClearError(); }
void Clear() { if(!data.IsPicked() && data) data->sock = NULL; data.Clear(); }

bool IsOpen() const { return data && data->IsOpen(); }

bool IsEof() const { return !data || data->IsEof(); }
bool IsError() const { return is_error; }
void ClearError() { is_error = false; errorcode = 0; errordesc.Clear(); }
int GetError() const { return errorcode; }
String GetErrorDesc() const { return errordesc; }

SOCKET GetSocket() const { return IsOpen() ? data->socket : INVALID_SOCKET; }
int GetNumber() const { return (int)GetSocket(); }

int GetKind() const { return data->GetKind(); }
Value GetInfo(String info) const { return data->GetInfo(info); }

String GetPeerAddr() const { return data->GetPeerAddr(); }

bool Accept(Socket& socket, dword *ipaddr = 0, bool nodelay = true, int timeout_msec = DEFAULT_CONNECT_TIMEOUT) { return data->Accept(socket, ipaddr, nodelay, timeout_msec); }
bool Close(int msecs_timeout = 0);

void NoDelay() { data->NoDelay(); }
void Linger(int msecs) { data->Linger(msecs); }
void NoLinger() { data->Linger(Null); }
void Block(bool b = true) { data->Block(b); }
void NoBlock() { data->Block(false); }

static bool Wait(const Vector<SOCKET>& read, const Vector<SOCKET>& write, int timeout_msec);
static bool Wait(const Vector<Socket *>& read, const Vector<Socket *>& write, int timeout_msec);

bool Peek(int timeout_msec = 0) { return data->Peek(timeout_msec, false); }
bool PeekWrite(int timeout_msec = 0) { return data->Peek(timeout_msec, true); }
bool PeekAbort(int timeout_msec = 0);
String PeekCount(int count, int timeout_msec = Null);
String PeekUntil(char term, int timeout_msec = Null, int maxlen = 1000000);

int ReadRaw(void *buffer, int maxlen) { return data->Read(buffer, maxlen); }
String Read(int timeout_msec = Null, int maxlen = 1000000);
int ReadCount(void *buffer, int count, int timeout_msec = Null);
String ReadCount(int count, int timeout_msec = Null);
String ReadUntil(char term, int timeout_msec = Null, int maxlen = 1000000);
String ReadUntil(Gate1<int> term, int& termchar, int timeout = Null, int maxlen = 1000000);
void UnRead(const void *buffer, int len);
void UnRead(String data) { UnRead(data.Begin(), data.GetLength()); }

int WriteRaw(const void *buffer, int maxlen) { return data->Write(buffer, maxlen); }
int WriteWait(const char *s, int length, int timeout_msec);
void Write(const char *s, int length) { WriteWait(s, length, Null); }
void Write(String s) { Write(s.Begin(), s.GetLength()); }

void StopWrite() { data->StopWrite(); }

static String GetHostName();

static String GetErrorText();
static void SetErrorText(String text);
static void ClearErrorText() { SetErrorText(Null); }

#if defined(PLATFORM_WIN32)
static int GetErrorCode() { return WSAGetLastError(); }
#define SOCKERR(x) WSA##x
#elif defined(PLATFORM_POSIX)
static int GetErrorCode() { return errno; }
#define SOCKERR(x) x
#else
#error Unsupported platform
#endif

protected:
void SetSockError(const char *context) { SetSockError(INVALID_SOCKET, context); }
void SetSockError(SOCKET socket, const char *context);
void SetSockError(SOCKET socket, const char *context, int code, const char *errordesc);

private:
One<Data> data;
bool is_error;
int errorcode;
String errordesc;

friend bool SSLSecureSocket(Socket& socket);
};

#ifdef PLATFORM_WIN32
class SocketEvent : public Event {
public:
SocketEvent() {}

void Read(Socket& socket);
void Write(Socket& socket);
void Accept(Socket& socket);
void Select(Socket& socket, int fd_flags);
};
#endif

bool ServerSocket(Socket& socket, int port, bool nodelay = true, int listen_count = 5, bool is_blocking = true, bool reuse = true);
bool ClientSocket(Socket& socket, const char *host, int port, bool nodelay = true, dword *my_addr = NULL, int timeout = DEFAULT_CONNECT_TIMEOUT, bool is_blocking = true);
void AttachSocket(Socket& socket, SOCKET s, bool blocking);

Change log

r4361 by cxl on Jan 5, 2012   Diff
*Web/SSL: HttpsClient now correctly uses
CONNECT for proxy
Go to: 
Project members, sign in to write a code review

Older revisions

r3379 by rylek on Apr 27, 2011   Diff
.Web: minor error-related fixes in
sockets
r3253 by rylek on Mar 1, 2011   Diff
.Web: fixed bug causing crash when
calling Socket::Clear on a picked
socket.
r3235 by rylek on Feb 22, 2011   Diff
+Web: added extended three-parameter
version of Socket::Data::SetSockError
to facilitate error handling in SSL
sockets; fixed end-of-file detection
in SSLSocketData::Read
All revisions of this file

File info

Size: 8104 bytes, 171 lines

File properties

svn:eol-style
native
Powered by Google Project Hosting