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
 * file.
 */

#define __NO_EXT_QNX

#include "config.h"

#include <string.h>

#include <errno.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())
		@throw [OFInitializationFailedException
		    exceptionWithClass: self];
}

+ (instancetype)socket
{
	return [[[self alloc] init] autorelease];







|
<
|


















|







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 <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_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
			  length: (size_t)length
{
	ssize_t ret;

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

	if (_atEndOfStream) {
		OFReadFailedException *e;

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

#ifndef _WIN32
	if ((ret = recv(_socket, buffer, length, 0)) < 0)
		@throw [OFReadFailedException exceptionWithObject: self

						  requestedLength: length];

#else
	if (length > UINT_MAX)
		@throw [OFOutOfRangeException exception];

	if ((ret = recv(_socket, buffer, (unsigned int)length, 0)) < 0)
		@throw [OFReadFailedException exceptionWithObject: self

						  requestedLength: length];

#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) {
		OFWriteFailedException *e;

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

#ifndef _WIN32
	if (send(_socket, buffer, length, 0) < length)
		@throw [OFWriteFailedException exceptionWithObject: self

						   requestedLength: length];

#else
	if (length > UINT_MAX)
		@throw [OFOutOfRangeException exception];

	if (send(_socket, buffer, (unsigned int)length, 0) < length)
		@throw [OFWriteFailedException exceptionWithObject: self

						   requestedLength: length];

#endif
}

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

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


}
#endif

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







|
<
<
|
|
|
<
<



|
>
|
>





|
>
|
>














|
<
<
|
|
|
<
<



|
>
|
>





|
>
|
>










|
>
>







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)


		@throw [OFReadFailedException exceptionWithObject: self
						  requestedLength: length
							    errNo: ENOTCONN];



#ifndef _WIN32
	if ((ret = recv(_socket, buffer, length, 0)) < 0)
		@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
				  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)


		@throw [OFWriteFailedException exceptionWithObject: self
						   requestedLength: length
							     errNo: ENOTCONN];



#ifndef _WIN32
	if (send(_socket, buffer, length, 0) < 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
				  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
				  errNo: of_socket_errno()];
}
#endif

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