Artifact 53952137a231627c1b8d6ae78647bcc10429e01bbdb12fcaa2956fd53cf6ccd0:
- File
src/OFStreamSocket.m
— part of check-in
[e5b2ee56ff]
at
2020-04-26 16:21:38
on branch trunk
— Add OFSequencedPacketSocket
This is intended for SCTP and SPX. (user: js, size: 4323) [annotate] [blame] [check-ins using]
/* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, * 2018, 2019, 2020 * Jonathan Schleifer <js@nil.im> * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in * the packaging of this file. * * Alternatively, it may be distributed under the terms of the GNU General * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #define __NO_EXT_QNX #include "config.h" #include <errno.h> #include <string.h> #import "OFStreamSocket.h" #import "OFInitializationFailedException.h" #import "OFNotImplementedException.h" #import "OFNotOpenException.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]; } - (instancetype)init { self = [super init]; @try { if (self.class == [OFStreamSocket class]) { [self doesNotRecognizeSelector: _cmd]; abort(); } _socket = INVALID_SOCKET; } @catch (id e) { [self release]; @throw e; } return self; } - (bool)lowlevelIsAtEndOfStream { if (_socket == INVALID_SOCKET) @throw [OFNotOpenException exceptionWithObject: self]; return _atEndOfStream; } - (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length { ssize_t ret; if (_socket == INVALID_SOCKET) @throw [OFNotOpenException exceptionWithObject: self]; #ifndef OF_WINDOWS if ((ret = recv(_socket, buffer, length, 0)) < 0) @throw [OFReadFailedException exceptionWithObject: self requestedLength: length errNo: of_socket_errno()]; #else if (length > INT_MAX) @throw [OFOutOfRangeException exception]; if ((ret = recv(_socket, buffer, (int)length, 0)) < 0) @throw [OFReadFailedException exceptionWithObject: self requestedLength: length errNo: of_socket_errno()]; #endif if (ret == 0) _atEndOfStream = true; return ret; } - (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length { if (_socket == INVALID_SOCKET) @throw [OFNotOpenException exceptionWithObject: self]; #ifndef OF_WINDOWS ssize_t bytesWritten; if (length > SSIZE_MAX) @throw [OFOutOfRangeException exception]; if ((bytesWritten = send(_socket, (void *)buffer, length, 0)) < 0) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length bytesWritten: 0 errNo: of_socket_errno()]; #else int bytesWritten; if (length > INT_MAX) @throw [OFOutOfRangeException exception]; if ((bytesWritten = send(_socket, buffer, (int)length, 0)) < 0) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length bytesWritten: 0 errNo: of_socket_errno()]; #endif return (size_t)bytesWritten; } #if defined(OF_WINDOWS) || defined(OF_AMIGAOS) - (void)setBlocking: (bool)enable { # ifdef OF_WINDOWS u_long v = enable; # else char v = enable; # endif if (ioctlsocket(_socket, FIONBIO, &v) == SOCKET_ERROR) @throw [OFSetOptionFailedException exceptionWithObject: self errNo: of_socket_errno()]; _blocking = enable; } #endif - (int)fileDescriptorForReading { #ifndef OF_WINDOWS return _socket; #else if (_socket == INVALID_SOCKET) return -1; if (_socket > INT_MAX) @throw [OFOutOfRangeException exception]; return (int)_socket; #endif } - (int)fileDescriptorForWriting { #ifndef OF_WINDOWS return _socket; #else if (_socket == INVALID_SOCKET) return -1; if (_socket > INT_MAX) @throw [OFOutOfRangeException exception]; return (int)_socket; #endif } - (void)close { if (_socket == INVALID_SOCKET) @throw [OFNotOpenException exceptionWithObject: self]; closesocket(_socket); _socket = INVALID_SOCKET; _atEndOfStream = false; [super close]; } - (void)dealloc { if (_socket != INVALID_SOCKET) [self close]; [super dealloc]; } @end