@@ -60,7 +60,132 @@ void InitialConnectionHandler::readCallback(
6060 bdlbb::Blob* blob,
6161 const InitialConnectionContextSp& context)
6262{
63- context->readCallback (status, numNeeded, blob);
63+ enum RcEnum {
64+ // Value for the various RC error categories
65+ rc_SUCCESS = 0 ,
66+ rc_READ_BLOB_ERROR = -1 ,
67+ rc_PROCESS_BLOB_ERROR = -2 ,
68+ };
69+
70+ BALL_LOG_TRACE << " InitialConnectionHandler readCb: [status: " << status
71+ << " , peer: '" << context->channel ()->peerUri () << " ']" ;
72+
73+ bsl::shared_ptr<mqbnet::Session> session;
74+ bmqu::MemOutStream errStream;
75+ bdlbb::Blob outPacket;
76+
77+ bool isFullBlob = true ;
78+ int rc = rc_SUCCESS;
79+ bsl::string error;
80+
81+ // The completeCb is not triggered only when there's more to read
82+ // (didn't receive a full blob; or received a full blob and
83+ // successfully scheduled another read)
84+ bdlb::ScopeExitAny guard (
85+ bdlf::BindUtil::bind (&InitialConnectionHandler::complete,
86+ context,
87+ bsl::ref (rc),
88+ bsl::ref (error),
89+ bsl::ref (session)));
90+
91+ rc = readBlob (errStream, &outPacket, &isFullBlob, status, numNeeded, blob);
92+ if (rc != rc_SUCCESS) {
93+ rc = (rc * 10 ) + rc_READ_BLOB_ERROR;
94+ error = bsl::string (errStream.str ().data (), errStream.str ().length ());
95+ return ; // RETURN
96+ }
97+
98+ if (!isFullBlob) {
99+ guard.release ();
100+ return ; // RETURN
101+ }
102+
103+ rc = processBlob (errStream, &session, outPacket, context);
104+ if (rc != rc_SUCCESS) {
105+ rc = (rc * 10 ) + rc_PROCESS_BLOB_ERROR;
106+ error = bsl::string (errStream.str ().data (), errStream.str ().length ());
107+ return ; // RETURN
108+ }
109+ }
110+
111+ int InitialConnectionHandler::readBlob (bsl::ostream& errorDescription,
112+ bdlbb::Blob* outPacket,
113+ bool * isFullBlob,
114+ const bmqio::Status& status,
115+ int * numNeeded,
116+ bdlbb::Blob* blob)
117+ {
118+ enum RcEnum {
119+ // Value for the various RC error categories
120+ rc_SUCCESS = 0 ,
121+ rc_READ_ERROR = -1 ,
122+ rc_UNRECOVERABLE_READ_ERROR = -2
123+ };
124+
125+ if (!status) {
126+ errorDescription << " Read error: " << status;
127+ return (10 * status.category ()) + rc_READ_ERROR; // RETURN
128+ }
129+
130+ int rc = bmqio::ChannelUtil::handleRead (outPacket, numNeeded, blob);
131+ if (rc != 0 ) {
132+ // This indicates a non recoverable error...
133+ errorDescription << " Unrecoverable read error:\n "
134+ << bmqu::BlobStartHexDumper (blob);
135+ return (rc * 10 ) + rc_UNRECOVERABLE_READ_ERROR; // RETURN
136+ }
137+
138+ if (outPacket->length () == 0 ) {
139+ // Don't yet have a full blob
140+ *isFullBlob = false ;
141+ return rc_SUCCESS; // RETURN
142+ }
143+
144+ // Have a full blob, indicate no more bytes needed (we have to do this
145+ // because 'handleRead' above set it back to 4 at the end).
146+ *numNeeded = 0 ;
147+
148+ return rc_SUCCESS;
149+ }
150+
151+ int InitialConnectionHandler::processBlob (
152+ bsl::ostream& errorDescription,
153+ bsl::shared_ptr<mqbnet::Session>* session,
154+ const bdlbb::Blob& blob,
155+ const InitialConnectionContextSp& context)
156+ {
157+ enum RcEnum {
158+ // Value for the various RC error categories
159+ rc_SUCCESS = 0 ,
160+ rc_INVALID_NEGOTIATION_MESSAGE = -1 ,
161+ };
162+
163+ bsl::optional<bmqp_ctrlmsg::NegotiationMessage> negotiationMsg;
164+
165+ int rc = decodeInitialConnectionMessage (errorDescription,
166+ blob,
167+ &negotiationMsg);
168+
169+ if (rc != 0 ) {
170+ return (rc * 10 ) + rc_INVALID_NEGOTIATION_MESSAGE; // RETURN
171+ }
172+
173+ if (negotiationMsg.has_value ()) {
174+ context->negotiationContext ()->setNegotiationMessage (
175+ negotiationMsg.value ());
176+
177+ rc = d_negotiator_mp->createSessionOnMsgType (errorDescription,
178+ session,
179+ context.get ());
180+ }
181+ else {
182+ errorDescription
183+ << " Decode NegotiationMessage succeeds but nothing is "
184+ " loaded into the NegotiationMessage." ;
185+ rc = (rc * 10 ) + rc_INVALID_NEGOTIATION_MESSAGE;
186+ }
187+
188+ return rc;
64189}
65190
66191int InitialConnectionHandler::decodeInitialConnectionMessage (
0 commit comments