1// PortConnection.cpp 2 3#include <stdio.h> 4 5#include "AutoDeleter.h" 6#include "PortConnection.h" 7 8namespace PortConnectionDefs { 9 10const int32 kProtocolVersion = 1; 11 12const char* kPortConnectionPortName = "NetFS port connection port"; 13 14// number of client up/down stream channels 15const int32 kMinUpStreamChannels = 1; 16const int32 kMaxUpStreamChannels = 10; 17const int32 kDefaultUpStreamChannels = 5; 18const int32 kMinDownStreamChannels = 1; 19const int32 kMaxDownStreamChannels = 5; 20const int32 kDefaultDownStreamChannels = 1; 21 22} // namespace PortConnectionDefs 23 24using namespace PortConnectionDefs; 25 26// #pragma mark - 27// #pragma mark ----- PortConnection ----- 28 29// constructor 30PortConnection::PortConnection() 31 : AbstractConnection(), 32 fUpStreamChannels(0), 33 fDownStreamChannels(0) 34{ 35} 36 37// destructor 38PortConnection::~PortConnection() 39{ 40} 41 42// Init (server side) 43status_t 44PortConnection::Init(Channel* channel, int32 upStreamChannels, 45 int32 downStreamChannels) 46{ 47 ObjectDeleter<Channel> deleter(channel); 48 status_t error = AbstractConnection::Init(); 49 if (error != B_OK) 50 return error; 51 // add the channel 52 error = AddDownStreamChannel(channel); 53 if (error != B_OK) 54 return error; 55 deleter.Detach(); 56 fUpStreamChannels = upStreamChannels; 57 fDownStreamChannels = downStreamChannels; 58 return B_OK; 59} 60 61// Init (client side) 62status_t 63PortConnection::Init(const char* parameters) 64{ 65 status_t error = AbstractConnection::Init(); 66 if (error != B_OK) 67 return error; 68 // parse the parameters 69 // parameter format is "[ <up> [ <down> ] ]" 70 int upStreamChannels = kDefaultUpStreamChannels; 71 int downStreamChannels = kDefaultDownStreamChannels; 72 if (parameters) 73 sscanf(parameters, "%d %d", &upStreamChannels, &downStreamChannels); 74 // get the server port 75 port_id serverPort = find_port(kPortConnectionPortName); 76 if (serverPort < 0) 77 return serverPort; 78 // create a client channel 79 PortChannel* channel; 80 error = _CreateChannel(&channel); 81 if (error != B_OK) 82 return error; 83 // add it as up stream channel 84 error = AddUpStreamChannel(channel); 85 if (error != B_OK) { 86 delete channel; 87 return error; 88 } 89 // send the server a connect request 90 ConnectRequest request; 91 request.protocolVersion = kProtocolVersion; 92 request.upStreamChannels = upStreamChannels; 93 request.downStreamChannels = downStreamChannels; 94 channel->GetInfo(&request.channelInfo); 95 error = write_port(serverPort, 0, &request, sizeof(ConnectRequest)); 96 if (error != B_OK) 97 return error; 98 // get the server reply 99 ConnectReply reply; 100 error = channel->Receive(&reply, sizeof(ConnectReply)); 101 if (error != B_OK) 102 return error; 103 error = reply.error; 104 if (error != B_OK) 105 return error; 106 upStreamChannels = reply.upStreamChannels; 107 downStreamChannels = reply.downStreamChannels; 108 int32 allChannels = upStreamChannels + downStreamChannels; 109 // create the channels 110 PortChannel::Info* infos = new(std::nothrow) 111 PortChannel::Info[allChannels - 1]; 112 if (!infos) 113 return B_NO_MEMORY; 114 ArrayDeleter<PortChannel::Info> _(infos); 115 for (int32 i = 1; i < allChannels; i++) { 116 // create a channel 117 PortChannel* otherChannel; 118 error = _CreateChannel(&otherChannel); 119 if (error != B_OK) 120 return error; 121 // add the channel 122 if (i < upStreamChannels) 123 error = AddUpStreamChannel(otherChannel); 124 else 125 error = AddDownStreamChannel(otherChannel); 126 if (error != B_OK) { 127 delete otherChannel; 128 return error; 129 } 130 // add the info 131 otherChannel->GetInfo(infos + i - 1); 132 } 133 // send the infos to the server 134 error = channel->Send(infos, sizeof(PortChannel::Info) * (allChannels - 1)); 135 if (error != B_OK) 136 return error; 137 return B_OK; 138} 139 140// FinishInitialization 141status_t 142PortConnection::FinishInitialization() 143{ 144 // get the down stream channel 145 Channel* channel = DownStreamChannelAt(0); 146 if (!channel) 147 return B_BAD_VALUE; 148 // send the connect reply 149 ConnectReply reply; 150 reply.error = B_OK; 151 reply.upStreamChannels = fUpStreamChannels; 152 reply.downStreamChannels = fDownStreamChannels; 153 status_t error = channel->Send(&reply, sizeof(ConnectReply)); 154 if (error != B_OK) 155 return error; 156 // receive the channel infos 157 int32 allChannels = fUpStreamChannels + fDownStreamChannels; 158 PortChannel::Info* infos = new(std::nothrow) 159 PortChannel::Info[allChannels - 1]; 160 if (!infos) 161 return B_NO_MEMORY; 162 ArrayDeleter<PortChannel::Info> _(infos); 163 error = channel->Receive(infos, 164 sizeof(PortChannel::Info) * (allChannels - 1)); 165 if (error != B_OK) 166 return error; 167 // create the channels 168 for (int32 i = 1; i < allChannels; i++) { 169 // create a channel 170 PortChannel* otherChannel; 171 error = _CreateChannel(&otherChannel, infos + i - 1, true); 172 if (error != B_OK) 173 return error; 174 // add the channel 175 if (i < fUpStreamChannels) // inverse, since we're on server side 176 error = AddDownStreamChannel(otherChannel); 177 else 178 error = AddUpStreamChannel(otherChannel); 179 if (error != B_OK) { 180 delete otherChannel; 181 return error; 182 } 183 } 184 return B_OK; 185} 186 187// _CreateChannel 188status_t 189PortConnection::_CreateChannel(PortChannel** _channel, PortChannel::Info* info, 190 bool inverse) 191{ 192 PortChannel* channel = (info ? new(std::nothrow) PortChannel(info, inverse) 193 : new(std::nothrow) PortChannel); 194 if (!channel) 195 return B_NO_MEMORY; 196 status_t error = channel->InitCheck(); 197 if (error != B_OK) { 198 delete channel; 199 return error; 200 } 201 *_channel = channel; 202 return B_OK; 203} 204 205