ObjFW  Diff

Differences From Artifact [70d50e1c9d]:

To Artifact [c547367b26]:

  • File src/OFStreamSocket.m — part of check-in [62e2de30b9] at 2015-02-16 08:39:17 on branch trunk — Explicitly pass errno to exceptions

    The old behaviour where the exception would access errno directly on
    creation of the exception was very fragile. The two main problems with
    it were that sometimes it would pick up an errno even though none had
    been set and in other cases that when the exception was created errno
    had already been overridden.

    This also greatly increases errno handling on Win32, especially in
    conjunction with sockets. It can still be improved further, though. (user: js, size: 3777) [annotate] [blame] [check-ins using]


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
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







-
+
-
-
+


















-
+







 * file.
 */

#define __NO_EXT_QNX

#include "config.h"

#include <string.h>
#include <errno.h>

#include <errno.h>
#include <string.h>

#import "OFStreamSocket.h"

#import "OFInitializationFailedException.h"
#import "OFNotConnectedException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFSetOptionFailedException.h"
#import "OFWriteFailedException.h"

#import "socket_helpers.h"

@implementation OFStreamSocket
+ (void)initialize
{
	if (self != [OFStreamSocket class])
		return;

	if (!of_init_sockets())
	if (!of_socket_init())
		@throw [OFInitializationFailedException
		    exceptionWithClass: self];
}

+ (instancetype)socket
{
	return [[[self alloc] init] autorelease];
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
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







-
+
-
-
-
-
-
+
+
+
-
-



-
-
+
+
+
+





-
-
+
+
+
+














-
+
-
-
-
-
-
+
+
+
-
-



-
-
+
+
+
+





-
-
+
+
+
+










-
+
+
+







			  length: (size_t)length
{
	ssize_t ret;

	if (_socket == INVALID_SOCKET)
		@throw [OFNotConnectedException exceptionWithSocket: self];

	if (_atEndOfStream) {
	if (_atEndOfStream)
		OFReadFailedException *e;

		e = [OFReadFailedException exceptionWithObject: self
					       requestedLength: length];
		e->_errNo = ENOTCONN;
		@throw [OFReadFailedException exceptionWithObject: self
						  requestedLength: length
							    errNo: ENOTCONN];
		@throw e;
	}

#ifndef _WIN32
	if ((ret = recv(_socket, buffer, length, 0)) < 0)
		@throw [OFReadFailedException exceptionWithObject: self
						  requestedLength: length];
		@throw [OFReadFailedException
		    exceptionWithObject: self
			requestedLength: length
				  errNo: of_socket_errno()];
#else
	if (length > UINT_MAX)
		@throw [OFOutOfRangeException exception];

	if ((ret = recv(_socket, buffer, (unsigned int)length, 0)) < 0)
		@throw [OFReadFailedException exceptionWithObject: self
						  requestedLength: length];
		@throw [OFReadFailedException
		    exceptionWithObject: self
			requestedLength: length
				  errNo: of_socket_errno()];
#endif

	if (ret == 0)
		_atEndOfStream = true;

	return ret;
}

- (void)lowlevelWriteBuffer: (const void*)buffer
		     length: (size_t)length
{
	if (_socket == INVALID_SOCKET)
		@throw [OFNotConnectedException exceptionWithSocket: self];

	if (_atEndOfStream) {
	if (_atEndOfStream)
		OFWriteFailedException *e;

		e = [OFWriteFailedException exceptionWithObject: self
						requestedLength: length];
		e->_errNo = ENOTCONN;
		@throw [OFWriteFailedException exceptionWithObject: self
						   requestedLength: length
							     errNo: ENOTCONN];
		@throw e;
	}

#ifndef _WIN32
	if (send(_socket, buffer, length, 0) < length)
		@throw [OFWriteFailedException exceptionWithObject: self
						   requestedLength: length];
		@throw [OFWriteFailedException
		    exceptionWithObject: self
			requestedLength: length
				  errNo: of_socket_errno()];
#else
	if (length > UINT_MAX)
		@throw [OFOutOfRangeException exception];

	if (send(_socket, buffer, (unsigned int)length, 0) < length)
		@throw [OFWriteFailedException exceptionWithObject: self
						   requestedLength: length];
		@throw [OFWriteFailedException
		    exceptionWithObject: self
			requestedLength: length
				  errNo: of_socket_errno()];
#endif
}

#ifdef _WIN32
- (void)setBlocking: (bool)enable
{
	u_long v = enable;
	_blocking = enable;

	if (ioctlsocket(_socket, FIONBIO, &v) == SOCKET_ERROR)
		@throw [OFSetOptionFailedException exceptionWithStream: self];
		@throw [OFSetOptionFailedException
		    exceptionWithStream: self
				  errNo: of_socket_errno()];
}
#endif

- (int)fileDescriptorForReading
{
#ifndef _WIN32
	return _socket;