xref: /haiku/src/add-ons/kernel/file_systems/netfs/shared/PortChannel.cpp (revision 4052469d007d17112b0fdf8814c92c77414a1398)
1 // PortChannel.cpp
2 
3 #include <new>
4 #include <string.h>
5 
6 #include "PortChannel.h"
7 #include "Utils.h"
8 
9 static const int32 kMaxPortMessageSize = 102400;	// 100 KB
10 static const int32 kDefaultBufferSize	= 10240;	// 10 KB
11 
12 // constructor
13 PortChannel::PortChannel()
14 	: Channel(),
15 	  fSendPort(-1),
16 	  fReceivePort(-1),
17 	  fBuffer(new(std::nothrow) uint8[kDefaultBufferSize]),
18 	  fBufferSize(kDefaultBufferSize),
19 	  fBufferOffset(0),
20 	  fBufferContentSize(0)
21 {
22 	fSendPort = create_port(10, "port connection send port");
23 	fReceivePort = create_port(10, "port connection receive port");
24 }
25 
26 // constructor
27 PortChannel::PortChannel(const Info* info, bool inverse)
28 	: Channel(),
29 	  fSendPort(inverse ? info->receivePort : info->sendPort),
30 	  fReceivePort(inverse ? info->sendPort : info->receivePort),
31 	  fBuffer(new(std::nothrow) uint8[kDefaultBufferSize]),
32 	  fBufferSize(kDefaultBufferSize),
33 	  fBufferOffset(0),
34 	  fBufferContentSize(0)
35 {
36 }
37 
38 // constructor
39 PortChannel::PortChannel(port_id sendPort, port_id receivePort)
40 	: Channel(),
41 	  fSendPort(sendPort),
42 	  fReceivePort(receivePort),
43 	  fBuffer(new(std::nothrow) uint8[kDefaultBufferSize]),
44 	  fBufferSize(kDefaultBufferSize),
45 	  fBufferOffset(0),
46 	  fBufferContentSize(0)
47 {
48 }
49 
50 // destructor
51 PortChannel::~PortChannel()
52 {
53 	delete[] fBuffer;
54 }
55 
56 // InitCheck
57 status_t
58 PortChannel::InitCheck() const
59 {
60 	if (fSendPort < 0)
61 		return fSendPort;
62 	if (fReceivePort < 0)
63 		return fReceivePort;
64 	if (!fBuffer)
65 		return B_NO_MEMORY;
66 	return B_OK;
67 }
68 
69 // GetInfo
70 void
71 PortChannel::GetInfo(Info* info) const
72 {
73 	if (info) {
74 		info->sendPort = fSendPort;
75 		info->receivePort = fReceivePort;
76 	}
77 }
78 
79 // Close
80 void
81 PortChannel::Close()
82 {
83 	if (fSendPort >= 0) {
84 		delete_port(fSendPort);
85 		fSendPort = -1;
86 	}
87 	if (fReceivePort >= 0) {
88 		delete_port(fReceivePort);
89 		fReceivePort = -1;
90 	}
91 }
92 
93 // Send
94 status_t
95 PortChannel::Send(const void* _buffer, int32 size)
96 {
97 	if (size == 0)
98 		return B_OK;
99 	if (!_buffer || size < 0)
100 		return B_BAD_VALUE;
101 	const uint8* buffer = static_cast<const uint8*>(_buffer);
102 	while (size > 0) {
103 		int32 sendSize = min(size, fBufferSize);
104 		status_t error = write_port(fSendPort, 0, buffer, size);
105 		if (error != B_OK)
106 			return error;
107 		size -= sendSize;
108 		buffer += sendSize;
109 	}
110 	return B_OK;
111 }
112 
113 // Receive
114 status_t
115 PortChannel::Receive(void* _buffer, int32 size)
116 {
117 	if (size == 0)
118 		return B_OK;
119 	if (!_buffer || size < 0)
120 		return B_BAD_VALUE;
121 	uint8* buffer = static_cast<uint8*>(_buffer);
122 	while (size > 0) {
123 		if (fBufferContentSize > 0) {
124 			// there's something in our buffer: just read from there
125 			int32 bytesRead = min(size, fBufferContentSize);
126 			memcpy(buffer, fBuffer + fBufferOffset, bytesRead);
127 			fBufferOffset += bytesRead;
128 			fBufferContentSize -= bytesRead;
129 			size -= bytesRead;
130 			buffer += bytesRead;
131 		} else {
132 			// nothing left in the buffer: we read from the port
133 			if (size > fBufferSize) {
134 				// we shall read more than what would fit into our buffer, so
135 				// we can directly read into the user buffer
136 				ssize_t bytesRead = read_port(fReceivePort, 0, buffer, size);
137 				if (bytesRead < 0)
138 					return bytesRead;
139 				size -= bytesRead;
140 				buffer += bytesRead;
141 			} else {
142 				// we read into our buffer
143 				ssize_t bytesRead = read_port(fReceivePort, 0, fBuffer,
144 					fBufferSize);
145 				if (bytesRead < 0)
146 					return bytesRead;
147 				fBufferOffset = 0;
148 				fBufferContentSize = bytesRead;
149 			}
150 		}
151 	}
152 	return B_OK;
153 }
154 
155