1 // PortConnection.cpp 2 3 #include <stdio.h> 4 5 #include "AutoDeleter.h" 6 #include "PortConnection.h" 7 8 namespace PortConnectionDefs { 9 10 const int32 kProtocolVersion = 1; 11 12 const char* kPortConnectionPortName = "NetFS port connection port"; 13 14 // number of client up/down stream channels 15 const int32 kMinUpStreamChannels = 1; 16 const int32 kMaxUpStreamChannels = 10; 17 const int32 kDefaultUpStreamChannels = 5; 18 const int32 kMinDownStreamChannels = 1; 19 const int32 kMaxDownStreamChannels = 5; 20 const int32 kDefaultDownStreamChannels = 1; 21 22 } // namespace PortConnectionDefs 23 24 using namespace PortConnectionDefs; 25 26 // #pragma mark - 27 // #pragma mark ----- PortConnection ----- 28 29 // constructor 30 PortConnection::PortConnection() 31 : AbstractConnection(), 32 fUpStreamChannels(0), 33 fDownStreamChannels(0) 34 { 35 } 36 37 // destructor 38 PortConnection::~PortConnection() 39 { 40 } 41 42 // Init (server side) 43 status_t 44 PortConnection::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) 62 status_t 63 PortConnection::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 141 status_t 142 PortConnection::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 188 status_t 189 PortConnection::_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