1 // Port.cpp 2 3 #include <new> 4 5 #include "AreaSupport.h" 6 #include "Compatibility.h" 7 #include "Port.h" 8 9 using std::nothrow; 10 11 // minimal and maximal port size 12 static const int32 kMinPortSize = 1024; // 1 kB 13 static const int32 kMaxPortSize = 64 * 1024; // 64 kB 14 15 // constructor 16 Port::Port(int32 size) 17 : fBuffer(NULL), 18 fCapacity(0), 19 fMessageSize(0), 20 fInitStatus(B_NO_INIT), 21 fOwner(true) 22 { 23 // adjust size to be within the sane bounds 24 if (size < kMinPortSize) 25 size = kMinPortSize; 26 else if (size > kMaxPortSize) 27 size = kMaxPortSize; 28 // allocate the buffer 29 fBuffer = new(nothrow) uint8[size]; 30 if (!fBuffer) { 31 fInitStatus = B_NO_MEMORY; 32 return; 33 } 34 // create the owner port 35 fInfo.owner_port = create_port(1, "port owner port"); 36 if (fInfo.owner_port < 0) { 37 fInitStatus = fInfo.owner_port; 38 return; 39 } 40 // create the client port 41 fInfo.client_port = create_port(1, "port client port"); 42 if (fInfo.client_port < 0) { 43 fInitStatus = fInfo.client_port; 44 return; 45 } 46 fInfo.size = size; 47 fCapacity = size; 48 fInitStatus = B_OK; 49 } 50 51 // constructor 52 Port::Port(const Info* info) 53 : fBuffer(NULL), 54 fCapacity(0), 55 fMessageSize(0), 56 fInitStatus(B_NO_INIT), 57 fOwner(false) 58 { 59 // check parameters 60 if (!info || info->owner_port < 0 || info->client_port < 0 61 || info->size < kMinPortSize || info->size > kMaxPortSize) { 62 return; 63 } 64 // allocate the buffer 65 fBuffer = new(nothrow) uint8[info->size]; 66 if (!fBuffer) { 67 fInitStatus = B_NO_MEMORY; 68 return; 69 } 70 // init the info 71 fInfo.owner_port = info->owner_port; 72 fInfo.client_port = info->client_port; 73 fInfo.size = info->size; 74 // init the other members 75 fCapacity = info->size; 76 fInitStatus = B_OK; 77 } 78 79 // destructor 80 Port::~Port() 81 { 82 Close(); 83 delete[] fBuffer; 84 } 85 86 // Close 87 void 88 Port::Close() 89 { 90 if (fInitStatus != B_OK) 91 return; 92 fInitStatus = B_NO_INIT; 93 // delete the ports only if we are the owner 94 if (fOwner) { 95 if (fInfo.owner_port >= 0) 96 delete_port(fInfo.owner_port); 97 if (fInfo.client_port >= 0) 98 delete_port(fInfo.client_port); 99 } 100 fInfo.owner_port = -1; 101 fInfo.client_port = -1; 102 } 103 104 // InitCheck 105 status_t 106 Port::InitCheck() const 107 { 108 return fInitStatus; 109 } 110 111 // GetInfo 112 const Port::Info* 113 Port::GetInfo() const 114 { 115 return &fInfo; 116 } 117 118 // GetBuffer 119 void* 120 Port::GetBuffer() const 121 { 122 return fBuffer; 123 } 124 125 // GetCapacity 126 int32 127 Port::GetCapacity() const 128 { 129 return fCapacity; 130 } 131 132 // GetMessage 133 void* 134 Port::GetMessage() const 135 { 136 return (fInitStatus == B_OK && fMessageSize > 0 ? fBuffer : NULL); 137 } 138 139 // GetMessageSize 140 int32 141 Port::GetMessageSize() const 142 { 143 return (fInitStatus == B_OK ? fMessageSize : 0); 144 } 145 146 // Send 147 status_t 148 Port::Send(int32 size) 149 { 150 if (fInitStatus != B_OK) 151 return fInitStatus; 152 if (size <= 0 || size > fCapacity) 153 return B_BAD_VALUE; 154 fMessageSize = 0; 155 port_id port = (fOwner ? fInfo.client_port : fInfo.owner_port); 156 status_t error; 157 do { 158 error = write_port(port, 0, fBuffer, size); 159 } while (error == B_INTERRUPTED); 160 return (fInitStatus = error); 161 } 162 163 // SendAndReceive 164 status_t 165 Port::SendAndReceive(int32 size) 166 { 167 status_t error = Send(size); 168 if (error != B_OK) 169 return error; 170 return Receive(); 171 } 172 173 // Receive 174 status_t 175 Port::Receive(bigtime_t timeout) 176 { 177 if (fInitStatus != B_OK) 178 return fInitStatus; 179 port_id port = (fOwner ? fInfo.owner_port : fInfo.client_port); 180 status_t error = B_OK; 181 do { 182 int32 code; 183 ssize_t bytesRead; 184 if (timeout >= 0) { 185 bytesRead = read_port_etc(port, &code, fBuffer, fCapacity, 186 B_RELATIVE_TIMEOUT, timeout); 187 } else 188 bytesRead = read_port(port, &code, fBuffer, fCapacity); 189 if (bytesRead < 0) 190 error = bytesRead; 191 else 192 fMessageSize = bytesRead; 193 } while (error == B_INTERRUPTED); 194 if (error == B_TIMED_OUT || error == B_WOULD_BLOCK) { 195 return error; 196 } 197 if (error != B_OK) 198 return (fInitStatus = error); 199 if (fMessageSize <= 0 || fMessageSize > fCapacity) { 200 fMessageSize = 0; 201 return B_BAD_DATA; 202 } 203 return B_OK; 204 } 205 206