1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
|
8 krisbash 1.4 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
|
13 mike 1.1 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15 krisbash 1.4 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
|
18 mike 1.1 **
|
19 krisbash 1.4 ** See the Apache 2 License for the specific language governing permissions
|
20 mike 1.1 ** and limitations under the License.
21 **
22 **==============================================================================
23 */
24
25 #include <assert.h>
26 #include "protocol.h"
|
27 mike 1.2 #include <sock/addr.h>
28 #include <sock/sock.h>
29 #include <sock/selector.h>
|
30 mike 1.1 #include <base/buf.h>
31 #include <base/log.h>
32 #include <base/result.h>
33 #include <base/user.h>
|
34 krisbash 1.4 #include <pal/strings.h>
35 #include <pal/format.h>
36 #include <pal/file.h>
37 #include <pal/sleep.h>
38
39 // #define ENABLE_TRACING 1
40 #ifdef ENABLE_TRACING
41 # define TRACING_LEVEL 4
42 # include <deprecated/logging/logging.h>
|
43 mike 1.1 #else
|
44 krisbash 1.4 # define LOGE2(a)
45 # define LOGW2(a)
46 # define LOGD2(a)
47 # define LOGX2(a)
|
48 mike 1.1 #endif
49
50 /*
51 **==============================================================================
52 **
53 ** Local definitions:
54 **
55 **==============================================================================
56 */
57
58 static const MI_Uint32 _MAGIC = 0xC764445E;
59
|
60 krisbash 1.4 /*
61 **==============================================================================
62 */
63 STRAND_DEBUGNAME1( ProtocolSocketServer, PostMsg );
64 STRAND_DEBUGNAME2( ProtocolFromSocket, PostMsg, ReadyToFinish );
65 STRAND_DEBUGNAME3( ProtocolConnector, PostMsg, ReadyToFinish, ConnectEvent );
66
67 /*
68 **==============================================================================
69 */
70
71 ProtocolSocket* _ProtocolSocket_Server_New(
72 _In_ ProtocolBase * protocolBase,
73 _In_ Sock sock );
74
75 /* helper functions result */
76 typedef enum _Protocol_CallbackResult
77 {
78 PRT_CONTINUE,
79 PRT_RETURN_TRUE,
80 PRT_RETURN_FALSE
81 krisbash 1.4 }
82 Protocol_CallbackResult;
83
84 /* Forward declaration */
85 static void _PrepareMessageForSending(
86 ProtocolSocket *handler);
87
88 static MI_Boolean _RequestCallbackWrite(
89 ProtocolSocket* handler);
90
91 static MI_Result _ProtocolSocketAndBase_Delete(
92 ProtocolSocketAndBase* self);
93
94
95
96 /*
97 **==============================================================================
98 */
99
100 static MI_Result _SendIN_IO_thread(
101 ProtocolBase* self,
102 krisbash 1.4 ProtocolSocket* sendSock,
103 Message* message);
104
105 static void _FreeAuthData(
106 ProtocolSocket* h);
107
108 static void _ProtocolSocket_Cleanup(ProtocolSocket* handler);
109
110 /* Signature must not have return type so we created this wrapper */
111 static void _SendIN_IO_thread_wrapper(void* self_, Message* message)
112 {
113 ProtocolSocket* self = (ProtocolSocket*) self_;
114 ProtocolBase* protocolBase = (ProtocolBase*)self->base.data;
115 MI_Result result;
116
117 result = _SendIN_IO_thread( protocolBase, self, message);
118
119 if(result != MI_RESULT_OK)
120 {
121 trace_ProtocolSocket_PostFailed( &self->strand.info.interaction, self->strand.info.interaction.other );
122 // This will do following things
123 krisbash 1.4 // 1. cleaning up the message if any and acking it
124 // 2. closing the other side
125 // 3. Setting the closeOtherScheduled flag which will drop all further Posts after this one and also skip this logic in the SELECTOR_REMOVE callback
126 _ProtocolSocket_Cleanup(self);
127 }
128 }
129
130 MI_INLINE
131 void _ProtocolSocket_Release(
132 _In_ ProtocolSocket* self,
133 _In_ CallSite cs)
134 {
135 ptrdiff_t ref = Atomic_Dec(&self->refCount);
136
137 #if defined(CONFIG_ENABLE_DEBUG)
138 {
139 trace_ProtocolSocket_Release(cs.file, (MI_Uint32)cs.line, self, (unsigned int)ref);
140 }
141 #endif /* defined(CONFIG_ENABLE_DEBUG) */
142
143 if (0 == ref)
144 krisbash 1.4 /* Free self pointer */
145 PAL_Free(self);
146
147 (void)cs;
148 }
149
150 #define ProtocolSocket_Release(self) \
151 _ProtocolSocket_Release(self, CALLSITE)
152
153 #ifdef _PREFAST_
154 #pragma prefast (push)
155 #pragma prefast (disable: 28931) // unused assignment of variable ref
156 #endif /* _PREFAST_ */
157
158 MI_INLINE
159 void _ProtocolSocket_Addref(
160 _In_ ProtocolSocket* self,
161 _In_ CallSite cs)
162 {
163 ptrdiff_t ref = Atomic_Inc(&self->refCount);
164
165 krisbash 1.4 (void)cs;
166 ((void)ref);
167 #if defined(CONFIG_ENABLE_DEBUG)
168 {
169 trace_ProtocolSocket_Addref(cs.file, (MI_Uint32)cs.line, self, (unsigned int)ref);
170 }
171 #endif /* defined(CONFIG_ENABLE_DEBUG) */
172 }
173
174 #ifdef _PREFAST_
175 #pragma prefast (pop)
176 #endif /* _PREFAST_ */
177
178 #define ProtocolSocket_Addref(self) \
179 _ProtocolSocket_Addref(self, CALLSITE)
180
181 MI_INLINE
182 void _ProtocolSocket_Delete(
183 _In_ ProtocolSocket* self)
184 {
185 ProtocolSocket_Release(self);
186 krisbash 1.4 }
187
188 MI_Result _AddProtocolSocket_Handler(
189 Selector* self,
190 ProtocolSocket* protocolSocket)
191 {
192 MI_Result r = MI_RESULT_OK;
193 ProtocolSocket_Addref(protocolSocket);
194 r = Selector_AddHandler(self, &(protocolSocket->base));
195 return r;
196 }
197
198 static void _ProtocolSocket_Cleanup(ProtocolSocket* handler)
|
199 mike 1.1 {
|
200 krisbash 1.4 if(handler->closeOtherScheduled)
201 return;
202
203 handler->closeOtherScheduled = MI_TRUE;
204
205 _FreeAuthData(handler);
206
207 /* free outstanding messages, batch */
208 if (handler->receivingBatch)
209 Batch_Destroy( handler->receivingBatch );
210
211 handler->receivingBatch = 0;
212
213 if (handler->message)
214 {
215 MI_Boolean internalMessage = Message_IsInternalMessage( handler->message );
216
217 Message_Release(handler->message);
218 handler->message = 0;
219
220 //ACK up if the message just sent was posted from up
221 krisbash 1.4 if (!internalMessage)
222 Strand_ScheduleAck( &handler->strand );
223 }
224
225 Sock_Close(handler->base.sock);
226
227 /* Mark handler as closed */
228 handler->base.sock = INVALID_SOCK;
|
229 mike 1.1
|
230 krisbash 1.4 Strand_ScheduleClose( &handler->strand );
231 }
|
232 mike 1.1
|
233 krisbash 1.4 /*
234 **==============================================================================
235 */
|
236 mike 1.1
|
237 krisbash 1.4 void _ProtocolSocket_CheckAbort( _In_ ProtocolSocket* self )
238 {
239 if( !self->strand.info.thisClosedOther )
240 {
241 MI_Uint64 currentTimeUsec = 0;
242 ProtocolBase* protocolBase = (ProtocolBase*)self->base.data;
|
243 mike 1.1
|
244 krisbash 1.4 trace_ProtocolSocket_TimeoutTrigger( self );
245 // provoke a timeout to close/delete the socket
246 PAL_Time(¤tTimeUsec);
247 self->base.fireTimeoutAt = currentTimeUsec;
248 Selector_Wakeup( protocolBase->selector, MI_TRUE );
249 }
|
250 mike 1.1 }
251
|
252 krisbash 1.4 #ifdef _PREFAST_
253 #pragma prefast (push)
254 #pragma prefast (disable: 26001) // bogus "we know the strand points to the middle of the ProtocolSocket struct" and Linux sal parser doesnt recognize something like _Readable_elements_(_Inexpressible_(ProtocolSocket))
255 #endif /* _PREFAST_ */
256
257 void _ProtocolSocket_Post( _In_ Strand* self_, _In_ Message* msg)
|
258 mike 1.1 {
|
259 krisbash 1.4 ProtocolSocket* self = FromOffset( ProtocolSocket, strand, self_ );
260 ProtocolBase* protocolBase = (ProtocolBase*)self->base.data;
261
262 DEBUG_ASSERT( NULL != self_ );
263
264 DEBUG_ASSERT(self->message == NULL);
265 self->base.mask &= ~SELECTOR_READ;
266
267 trace_ProtocolSocket_PostingOnInteraction( &self->strand.info.interaction, self->strand.info.interaction.other );
268
269 if( self->closeOtherScheduled ||
270 ( MI_RESULT_OK != Selector_CallInIOThread(
271 protocolBase->selector, _SendIN_IO_thread_wrapper, self, msg ) ))
272 {
273 trace_ProtocolSocket_PostFailed( &self->strand.info.interaction, self->strand.info.interaction.other );
274 Strand_ScheduleAck( &self->strand );
275 }
276 }
277
278 void _ProtocolSocket_PostControl( _In_ Strand* self, _In_ Message* msg)
279 {
280 krisbash 1.4 DEBUG_ASSERT( MI_FALSE ); // not used yet
281 }
282
283 void _ProtocolSocket_Cancel( _In_ Strand* self_)
284 {
285 ProtocolSocket* self = FromOffset( ProtocolSocket, strand, self_ );
286
287 trace_ProtocolSocket_CancelReceived(
288 self->strand.info.thisClosedOther,
289 &self->strand.info.interaction,
290 self->strand.info.interaction.other );
291
292 // Abort the socket
293 _ProtocolSocket_CheckAbort( self );
294 }
295
296 void _ProtocolSocket_Ack( _In_ Strand* self_)
297 {
298 ProtocolSocket* self = FromOffset( ProtocolSocket, strand, self_ );
299 ProtocolBase* protocolBase = (ProtocolBase*)self->base.data;
300 DEBUG_ASSERT( NULL != self_ );
301 krisbash 1.4
302 trace_ProtocolSocket_Ack( &self_->info.interaction, self_->info.interaction.other );
303 if (!(self->base.mask & SELECTOR_WRITE))
304 self->base.mask |= SELECTOR_READ;
305 Selector_Wakeup( protocolBase->selector, MI_FALSE );
306 }
307
308 void _ProtocolSocket_Close( _In_ Strand* self_)
309 {
310 ProtocolSocket* self = FromOffset( ProtocolSocket, strand, self_ );
311
312 trace_ProtocolSocket_Close(
313 self->strand.info.thisClosedOther,
314 &self->strand.info.interaction,
315 self->strand.info.interaction.other );
316
317 if( !self->strand.canceled )
318 {
319 _ProtocolSocket_CheckAbort( self );
320 }
321 }
322 krisbash 1.4
323 void _ProtocolSocket_Finish( _In_ Strand* self_)
324 {
325 ProtocolSocket* self = FromOffset( ProtocolSocket, strand, self_ );
326 ProtocolBase* protocolBase = (ProtocolBase*)self->base.data;
327 DEBUG_ASSERT( NULL != self_ );
328
329 trace_ProtocolSocket_Finish( self );
330
331 if( protocolBase->type == PRT_TYPE_LISTENER )
332 {
333 _ProtocolSocket_Delete( self );
334 }
335 else
336 {
337 _ProtocolSocketAndBase_Delete( (ProtocolSocketAndBase*)self );
338 }
|
339 mike 1.1 }
340
|
341 krisbash 1.4 // PROTOCOLSOCKET_STRANDAUX_POSTMSG
342 void _ProtocolSocket_Aux_PostMsg( _In_ Strand* self_)
|
343 mike 1.1 {
|
344 krisbash 1.4 ProtocolSocket* self = FromOffset( ProtocolSocket, strand, self_ );
345 ProtocolBase* protocolBase = (ProtocolBase*)self->base.data;
346 Message * msg = self->strand.info.otherMsg;
347
348 self->strand.info.otherMsg = NULL;
349
350 if( !self->strand.info.thisClosedOther )
351 {
352 // process the case where the interaction for the connection has not been opened yet
353 if( NULL != protocolBase->callback && NULL == self->strand.info.interaction.other )
354 {
355 Strand_Open( self_, protocolBase->callback, protocolBase->callbackData, NULL, MI_FALSE );
356 }
357
358 if( Message_IsRequest(msg) )
359 {
360 RequestMsg* request = (RequestMsg*)msg;
361 AuthInfo_Copy( &request->authInfo, &self->authInfo );
362 }
363
364 DEBUG_ASSERT( NULL != self->strand.info.interaction.other );
|
365 mike 1.1
|
366 krisbash 1.4 // Leave the strand for the case where this is a new request on server
367 // and the provider is in-proc and takes over the thread
368 Strand_PostAndLeaveStrand( &self->strand, msg );
369 }
|
370 mike 1.1
|
371 krisbash 1.4 // now we can remove the reference added before Strand_ScheduleAux( PROTOCOLSOCKET_STRANDAUX_POSTMSG )
372 Message_Release( msg );
373 }
|
374 mike 1.1
|
375 krisbash 1.4 // PROTOCOLSOCKET_STRANDAUX_READYTOFINISH
376 void _ProtocolSocket_Aux_ReadyToFinish( _In_ Strand* self_)
377 {
378 Strand_ResetDelayFinish(self_);
379 }
|
380 mike 1.1
|
381 krisbash 1.4 // PROTOCOLSOCKET_STRANDAUX_CONNECTEVENT
382 void _ProtocolSocket_Aux_ConnectEvent( _In_ Strand* self_)
|
383 mike 1.1 {
|
384 krisbash 1.4 ProtocolSocket* self = FromOffset( ProtocolSocket, strand, self_ );
385 ProtocolEventConnect* msg = ProtocolEventConnect_New(self->isConnected);
386
387 DEBUG_ASSERT( NULL != self->strand.info.interaction.other );
388
389 Strand_PostControl( &self->strand, &msg->base );
390 Message_Release(&msg->base);
|
391 mike 1.1 }
392
|
393 krisbash 1.4 #ifdef _PREFAST_
394 #pragma prefast (pop)
395 #endif /* _PREFAST_ */
|
396 mike 1.1
|
397 krisbash 1.4 /*
398 Object that implements the binary protocol endpoint on a TCP Socket
399 There are 3 different types of objects that can be created:
400 - ProtocolSocketServer each client connection ON server side
401 - ProtocolConnector client connection TO the server
402 - ProtocolFromSocket either side of the out-of-proc (agent) connection
403
404 Behaviour:
405 - Post tries to schedule the operation on the IO thread (thru selector)
406 if that fails it sends the Ack immediately
407 - Post control is not implemented
408 - both Cancel and Close check if the connection has already been closed and
409 if not it triggers a timeout that will close it
410 - Ack reactivates keep reading by setting SELECTOR_READ (if no
411 write is in progress)
412 - Shutdown:
413 The ProtocolSocketServer objects are shutdown/deleted thru the normal
414 Strand logic (once the interaction is closed).
415 However the other Protocol objects are not deleted that way and instead
416 they are deleted manually by the object that uses them once it has
417 finished its Protocol_Run execution. That works by setting Strand_SetDelayFinish
418 krisbash 1.4 (which sets the delayFinish flag on the strand) on object creation,
419 and then calling ProtocolSocketAndBase_ReadyToFinish which schedules
420 the auxiliary function PROTOCOLSOCKET_STRANDAUX_CONNECTEVENT
421 which in turn disables that flag allowing the object to be deleted.
422
423 Unique features and special Behavour:
424 - When a complete message has been read instead of scheduling a post
425 the auxiliary function PROTOCOLSOCKET_STRANDAUX_POSTMSG is
426 scheduled instead. That function takes care of opening the interaction
427 (if not opened already) and posting using Strand_PostAndLeaveStrand
428 (which avoids holding the strand in case the thread is going to be hijacked
429 by the provider in the processing of that post).
430 - On the ProtocolConnector type once the connection succeds of fails
431 a PostControl notifies of that event by scheduling the auxiliary function
432 PROTOCOLSOCKET_STRANDAUX_CONNECTEVENT
433 */
434 static StrandFT _ProtocolSocket_FT = {
435 _ProtocolSocket_Post,
436 _ProtocolSocket_PostControl,
437 _ProtocolSocket_Ack,
438 _ProtocolSocket_Cancel,
439 krisbash 1.4 _ProtocolSocket_Close,
440 _ProtocolSocket_Finish,
441 NULL,
442 _ProtocolSocket_Aux_PostMsg,
443 _ProtocolSocket_Aux_ReadyToFinish,
444 _ProtocolSocket_Aux_ConnectEvent,
445 NULL,
446 NULL };
|
447 mike 1.1
448 /**************** Auth-support **********************************************************/
449 /* remove auth file and free auth data */
450 static void _FreeAuthData(
|
451 krisbash 1.4 ProtocolSocket* h)
|
452 mike 1.1 {
453 if (h->authData)
454 {
455 #if defined(CONFIG_POSIX)
456 unlink(h->authData->path);
457 #endif
|
458 krisbash 1.4 PAL_Free(h->authData);
|
459 mike 1.1 h->authData = 0;
460 }
461 }
462
463 /* Creates and sends authentication request message */
464 static MI_Boolean _SendAuthRequest(
|
465 krisbash 1.4 ProtocolSocket* h,
|
466 mike 1.1 const char* user,
467 const char* password,
468 const char* fileContent)
469 {
470 BinProtocolNotification* req;
|
471 krisbash 1.4 MI_Boolean retVal = MI_TRUE;
|
472 mike 1.1
473 req = BinProtocolNotification_New(BinNotificationConnectRequest);
474
475 if (!req)
476 return MI_FALSE;
477
478 if (user && *user)
|
479 krisbash 1.4 {
|
480 mike 1.1 req->user = Batch_Strdup(req->base.batch, user);
|
481 krisbash 1.4 if (!req->user)
482 {
483 BinProtocolNotification_Release(req);
484 return MI_FALSE;
485 }
486 }
|
487 mike 1.1
488 if (password && *password)
|
489 krisbash 1.4 {
|
490 mike 1.1 req->password = Batch_Strdup(req->base.batch, password);
|
491 krisbash 1.4 if (!req->password)
492 {
493 BinProtocolNotification_Release(req);
494 return MI_FALSE;
495 }
496 }
|
497 mike 1.1
498 req->uid = geteuid();
499 req->gid = getegid();
500
501 if (fileContent)
502 {
503 memcpy(req->authData, fileContent, sizeof(req->authData));
504 }
505
506 /* send message */
507 {
|
508 krisbash 1.4 DEBUG_ASSERT(h->message == NULL);
509 h->message = (Message*) req;
|
510 mike 1.1
511 Message_AddRef(&req->base);
512
513 _PrepareMessageForSending(h);
|
514 krisbash 1.4 retVal = _RequestCallbackWrite(h);
|
515 mike 1.1 }
516
517 BinProtocolNotification_Release(req);
518
|
519 krisbash 1.4 return retVal;
|
520 mike 1.1 }
521
522 static MI_Boolean _SendAuthResponse(
|
523 krisbash 1.4 ProtocolSocket* h,
|
524 mike 1.1 MI_Result result,
525 const char* path)
526 {
527 BinProtocolNotification* req;
|
528 krisbash 1.4 MI_Boolean retVal = MI_TRUE;
|
529 mike 1.1
530 req = BinProtocolNotification_New(BinNotificationConnectResponse);
531
532 if (!req)
533 return MI_FALSE;
534
535 req->result = result;
536 if (path && *path)
|
537 krisbash 1.4 {
|
538 mike 1.1 req->authFile = Batch_Strdup(req->base.batch, path);
|
539 krisbash 1.4 if (!req->authFile)
540 {
541 BinProtocolNotification_Release(req);
542 return MI_FALSE;
543 }
544 }
|
545 mike 1.1
546 /* send message */
547 {
|
548 krisbash 1.4 DEBUG_ASSERT(h->message == NULL);
549 h->message = (Message*)req;
|
550 mike 1.1 Message_AddRef(&req->base);
551
552 _PrepareMessageForSending(h);
|
553 krisbash 1.4 retVal = _RequestCallbackWrite(h);
|
554 mike 1.1 }
555
556 BinProtocolNotification_Release(req);
557
|
558 krisbash 1.4 return retVal;
|
559 mike 1.1 }
560
561 /*
|
562 krisbash 1.4 Processes auht message while waiting second connect request
|
563 mike 1.1 with content of the file.
564 Updates auth states correspondingly.
565 Parameters:
566 handler - socket handler
567 binMsg - BinProtocolNotification message with connect request/response
568
569 Return:
570 "TRUE" if connection should stay open; "FALSE" if auth failed
571 and conneciton should be closed immediately
572 */
573 static MI_Boolean _ProcessAuthMessageWaitingConnectRequestFileData(
|
574 krisbash 1.4 ProtocolSocket* handler,
|
575 mike 1.1 BinProtocolNotification* binMsg)
576 {
577 /* un-expected message */
578 if (BinNotificationConnectRequest != binMsg->type)
579 return MI_FALSE;
580
581 /* Check internal state */
582 if (!handler->authData)
583 return MI_FALSE;
584
585 if (0 == memcmp(binMsg->authData, handler->authData->authRandom, AUTH_RANDOM_DATA_SIZE))
586 {
587 if (!_SendAuthResponse(handler, MI_RESULT_OK, NULL))
588 return MI_FALSE;
589
590 /* Auth ok */
591 handler->authState = PRT_AUTH_OK;
592 _FreeAuthData(handler);
593
594 /* Get gid from user name */
|
595 krisbash 1.4 if (0 != GetUserGidByUid(handler->authInfo.uid, &handler->authInfo.gid))
|
596 mike 1.1 {
|
597 krisbash 1.4 trace_CannotGetUserGidForUid((int)handler->authInfo.uid);
|
598 mike 1.1 return MI_FALSE;
599 }
600
601 return MI_TRUE;
602 }
603
|
604 krisbash 1.4 trace_AuthFailed_RandomDataMismatch();
|
605 mike 1.1
606 /* Auth failed */
607 _SendAuthResponse(handler, MI_RESULT_ACCESS_DENIED, NULL);
608 handler->authState = PRT_AUTH_FAILED;
609 return MI_FALSE;
610 }
611
612 /*
|
613 krisbash 1.4 Processes auht message while waiting connect request
|
614 mike 1.1 Updates auth states correspondingly.
615 Parameters:
616 handler - socket handler
617 binMsg - BinProtocolNotification message with connect request/response
618
619 Return:
620 "TRUE" if connection should stay open; "FALSE" if auth failed
|
621 krisbash 1.4 and connection should be closed immediately
|
622 mike 1.1 */
623 static MI_Boolean _ProcessAuthMessageWaitingConnectRequest(
|
624 krisbash 1.4 ProtocolSocket* handler,
|
625 mike 1.1 BinProtocolNotification* binMsg)
626 {
627 /* un-expected message */
628 if (BinNotificationConnectRequest != binMsg->type)
629 return MI_FALSE;
630
631 /* Use explicit credentials if provided */
632 if (binMsg->user)
633 {
634 /* use empty password if not set */
635 if (!binMsg->password)
636 binMsg->password = "";
637
|
638 krisbash 1.4 if (0 == AuthenticateUser(binMsg->user, binMsg->password) &&
639 0 == LookupUser(binMsg->user, &handler->authInfo.uid, &handler->authInfo.gid))
|
640 mike 1.1 {
641 if (!_SendAuthResponse(handler, MI_RESULT_OK, NULL))
642 return MI_FALSE;
643
644 /* Auth ok */
645 handler->authState = PRT_AUTH_OK;
646 _FreeAuthData(handler);
647 return MI_TRUE;
648 }
649
|
650 krisbash 1.4 trace_AuthFailed_ForUser(scs(binMsg->user));
|
651 mike 1.1
652 /* Auth failed */
653 _SendAuthResponse(handler, MI_RESULT_ACCESS_DENIED, NULL);
654 handler->authState = PRT_AUTH_FAILED;
655 return MI_FALSE;
656 }
657
|
658 krisbash 1.4 /* If system supports connection-based auth, use it for
|
659 mike 1.1 implicit auth */
|
660 krisbash 1.4 if (0 == GetUIDByConnection((int)handler->base.sock, &handler->authInfo.uid, &handler->authInfo.gid))
|
661 mike 1.1 {
662 if (!_SendAuthResponse(handler, MI_RESULT_OK, NULL))
663 return MI_FALSE;
664
665 /* Auth ok */
666 handler->authState = PRT_AUTH_OK;
667 return MI_TRUE;
668 }
669 #if defined(CONFIG_OS_WINDOWS)
670 {
671 if (!_SendAuthResponse(handler, MI_RESULT_OK, NULL))
672 return MI_FALSE;
673
|
674 krisbash 1.4 /* Ignore Auth by setting it to OK */
675 handler->authInfo.uid = -1;
676 handler->authInfo.gid = -1;
|
677 mike 1.1 handler->authState = PRT_AUTH_OK;
678 return MI_TRUE;
679 }
680 #else
681
|
682 krisbash 1.4 /* If valid uid provided, try implicit credentials (file-based)
|
683 mike 1.1 gid will be taken from user name */
684 {
|
685 krisbash 1.4 handler->authData = (Protocol_AuthData*)PAL_Calloc(1, sizeof(Protocol_AuthData));
|
686 mike 1.1
687 if (!handler->authData)
688 {
689 /* Auth failed */
690 _SendAuthResponse(handler, MI_RESULT_ACCESS_DENIED, NULL);
691 handler->authState = PRT_AUTH_FAILED;
692 return MI_FALSE;
693 }
694
695 if (0 != CreateAuthFile(binMsg->uid, handler->authData->authRandom, AUTH_RANDOM_DATA_SIZE, handler->authData->path))
696 {
|
697 krisbash 1.4 trace_CannotCreateFileForUser((int)binMsg->uid);
|
698 mike 1.1
699 /* Auth failed */
700 _SendAuthResponse(handler, MI_RESULT_ACCESS_DENIED, NULL);
701 handler->authState = PRT_AUTH_FAILED;
702 return MI_FALSE;
703 }
704
705 /* send file name to the client */
706 if (!_SendAuthResponse(handler, MI_RESULT_IN_PROGRESS, handler->authData->path))
707 return MI_FALSE;
708
709 /* Auth posponed */
710 handler->authState = PRT_AUTH_WAIT_CONNECTION_REQUEST_WITH_FILE_DATA;
711
712 /* Remember uid we used to create file */
|
713 krisbash 1.4 handler->authInfo.uid = binMsg->uid;
714 handler->authInfo.gid = -1;
|
715 mike 1.1
716 return MI_TRUE;
717
718 }
719 #endif
720 }
721
722 /*
723 Processes auht message (either connect request or connect-response)
724 Updates auth states correspondingly.
725 Parameters:
726 handler - socket handler
727 msg - BinProtocolNotification message with connect request/response
728
729 Return:
730 "TRUE" if connection should stay open; "FALSE" if auth failed
731 and conneciton should be closed immediately
732 */
733 static MI_Boolean _ProcessAuthMessage(
|
734 krisbash 1.4 ProtocolSocket* handler,
|
735 mike 1.1 Message *msg)
736 {
|
737 krisbash 1.4 ProtocolBase* protocolBase = (ProtocolBase*)handler->base.data;
|
738 mike 1.1 BinProtocolNotification* binMsg;
739
740 if (msg->tag != BinProtocolNotificationTag)
741 return MI_FALSE;
742
743 binMsg = (BinProtocolNotification*) msg;
744
745 /* server waiting client's first request? */
746 if (PRT_AUTH_WAIT_CONNECTION_REQUEST == handler->authState)
747 {
748 return _ProcessAuthMessageWaitingConnectRequest(handler, binMsg);
749 }
750
751 /* server waiting for client's file's content request? */
752 if (PRT_AUTH_WAIT_CONNECTION_REQUEST_WITH_FILE_DATA == handler->authState)
753 {
754 return _ProcessAuthMessageWaitingConnectRequestFileData(handler, binMsg);
755 }
756
757 /* client waiting for server's response? */
758 if (PRT_AUTH_WAIT_CONNECTION_RESPONSE == handler->authState)
759 mike 1.1 {
760 /* un-expected message */
761 if (BinNotificationConnectResponse != binMsg->type)
762 return MI_FALSE;
763
764 if (binMsg->result == MI_RESULT_OK)
765 {
766 handler->authState = PRT_AUTH_OK;
767
|
768 krisbash 1.4 if( Atomic_Swap(&handler->connectEventSent, 1) == 0 )
769 {
770 DEBUG_ASSERT( PRT_TYPE_CONNECTOR == protocolBase->type );
771 handler->isConnected = MI_TRUE;
772 Strand_ScheduleAux( &handler->strand, PROTOCOLSOCKET_STRANDAUX_CONNECTEVENT );
773 }
774
|
775 mike 1.1 return MI_TRUE;
776 }
777 else if (binMsg->result == MI_RESULT_IN_PROGRESS && binMsg->authFile)
778 {
779 /* send back file's content */
780 char buf[AUTH_RANDOM_DATA_SIZE];
|
781 krisbash 1.4 FILE* is = File_Open(binMsg->authFile, "r");
|
782 mike 1.1
783 if (!is)
784 {
|
785 krisbash 1.4 trace_CannotOpenAuthFile(scs(binMsg->authFile));
|
786 mike 1.1 return MI_FALSE;
787 }
788
789 /* Read auth data from the file. */
790 if (sizeof(buf) != fread(buf, 1, sizeof(buf), is))
791 {
|
792 krisbash 1.4 trace_CannotReadAuthFile(scs(binMsg->authFile));
793 File_Close(is);
|
794 mike 1.1 return MI_FALSE;
795 }
796
|
797 krisbash 1.4 File_Close(is);
|
798 mike 1.1 return _SendAuthRequest(handler, 0, 0, buf);
799 }
800 else
801 {
|
802 krisbash 1.4 // PROTOCOLEVENT_DISCONNECT
803 if( PRT_TYPE_CONNECTOR == protocolBase->type )
|
804 mike 1.1 {
|
805 krisbash 1.4 if( Atomic_Swap(&handler->connectEventSent, 1) == 0 )
|
806 mike 1.1 {
|
807 krisbash 1.4 DEBUG_ASSERT( !handler->isConnected );
808 Strand_ScheduleAux( &handler->strand, PROTOCOLSOCKET_STRANDAUX_CONNECTEVENT );
|
809 mike 1.1 }
810 }
811 }
812
813 return MI_FALSE;
814 }
815
816 /* unknown state? */
817 return MI_FALSE;
818 }
819
820 static void _PrepareMessageForSending(
|
821 krisbash 1.4 ProtocolSocket *handler)
|
822 mike 1.1 {
|
823 krisbash 1.4 DEBUG_ASSERT(handler->message != NULL);
|
824 mike 1.1
825 /* reset sending attributes */
826 handler->sendingPageIndex = 0;
827 handler->sentCurrentBlockBytes = 0;
828
829 memset(&handler->send_buffer,0,sizeof(handler->send_buffer));
830 handler->send_buffer.base.magic = PROTOCOL_MAGIC;
831 handler->send_buffer.base.version = PROTOCOL_VERSION;
832 handler->send_buffer.base.pageCount = (MI_Uint32)Batch_GetPageCount(handler->message->batch);
833 handler->send_buffer.base.originalMessagePointer = handler->message;
834
835 /* ATTN! */
|
836 krisbash 1.4 DEBUG_ASSERT (handler->send_buffer.base.pageCount <= PROTOCOL_HEADER_MAX_PAGES);
|
837 mike 1.1
838 /* get page info */
839
840 Batch_GetPageInfo(
841 handler->message->batch, handler->send_buffer.batchInfo);
842
843 /* mark handler as 'want-write' */
844 handler->base.mask |= SELECTOR_WRITE;
845
846 }
847
848 static MI_Boolean _RequestCallbackWrite(
|
849 krisbash 1.4 ProtocolSocket* handler)
|
850 mike 1.1 {
851 /* try to write to socket as much as possible */
852 size_t sent;
853 MI_Result r;
|
854 krisbash 1.4 size_t retries = 0;
|
855 mike 1.1
|
856 krisbash 1.4 for (;;)
|
857 mike 1.1 {
858 /* buffers to write */
|
859 krisbash 1.4 IOVec buffers[32];
|
860 mike 1.1 size_t counter;
861
862 if ( !handler->message )
863 { /* nothing to send */
864 handler->base.mask &= ~SELECTOR_WRITE;
|
865 krisbash 1.4 if (!handler->strand.info.thisAckPending)
866 handler->base.mask |= SELECTOR_READ;
867 trace_SocketSendCompleted(handler);
|
868 mike 1.1 return MI_TRUE;
869 }
870
871 for ( counter = 0; counter < MI_COUNT(buffers); counter++ )
872 {
873 const char* buf;
874 MI_Uint32 index = (MI_Uint32)(handler->sendingPageIndex + counter);
875
|
876 krisbash 1.4 buf = (index == 0) ?
877 &handler->send_buffer :
|
878 mike 1.1 handler->send_buffer.batchInfo[index - 1].pagePointer;
879
880 if (!counter)
881 buf += handler->sentCurrentBlockBytes;
882
883 buffers[counter].ptr = (void*)buf;
884
885 buffers[counter].len = (index == 0) ? (sizeof(HeaderBase) + sizeof(Header_BatchInfoItem) * handler->send_buffer.base.pageCount)
886 : handler->send_buffer.batchInfo[index - 1].pageSize;
887
888 if (!counter)
889 buffers[counter].len -= handler->sentCurrentBlockBytes;
890
|
891 krisbash 1.4 if (index == handler->send_buffer.base.pageCount)
|
892 mike 1.1 {
893 counter++;
894 break;
895 }
896 }
897
898 sent = 0;
899
|
900 krisbash 1.4 do
901 {
902 r = Sock_WriteV(handler->base.sock, buffers, counter, &sent);
|
903 mike 1.1
|
904 krisbash 1.4 LOGD2((ZT("_RequestCallbackWrite - Sent %lu bytes with result %d (%s)"), sent, (int)r, mistrerror(r)));
|
905 mike 1.1
|
906 krisbash 1.4 if ( r == MI_RESULT_OK && 0 == sent )
907 {
908 trace_Socket_ConnectionClosed(handler);
909 return MI_FALSE; /* connection closed */
910 }
|
911 mike 1.1
|
912 krisbash 1.4 if (r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK)
913 {
914 trace_Socket_Sending_Error(handler, r);
915 if( r == MI_RESULT_NOT_FOUND && retries < 5 )
916 {
917 ++retries;
918 Sleep_Milliseconds(100);
919 continue;
920 }
921 return MI_FALSE;
922 }
923 }
924 while (r == MI_RESULT_NOT_FOUND);
|
925 mike 1.1
926 if (!sent)
|
927 krisbash 1.4 {
928 /* trace_QueueingSocket(handler); */
|
929 mike 1.1 return MI_TRUE;
|
930 krisbash 1.4 }
|
931 mike 1.1
932 /* update index */
933 for ( counter = 0; counter < MI_COUNT(buffers); counter++ )
934 {
935 if (!sent)
936 break;
937
938 if (sent >= buffers[counter].len)
939 {
940 sent -= buffers[counter].len;
941 handler->sendingPageIndex++;
942 handler->sentCurrentBlockBytes = 0;
943 continue;
944 }
945
946 handler->sentCurrentBlockBytes += sent;
947 break;
948 }
949
|
950 krisbash 1.4 if (handler->sendingPageIndex - 1 == (int)handler->send_buffer.base.pageCount)
|
951 mike 1.1 {
|
952 krisbash 1.4 MI_Boolean internalMessage = Message_IsInternalMessage( handler->message );
953
954 LOGD2((ZT("_RequestCallbackWrite - Message sent. tag %d (%s)"), handler->message->tag, messagetagnamestr(handler->message->tag)));
|
955 mike 1.1
|
956 krisbash 1.4 //for all protocol internal messages, i.e messages that were not posted from up
|
957 mike 1.1 /* next message */
958 Message_Release(handler->message);
959 handler->message = 0;
960
|
961 krisbash 1.4 //ACK up if the message just sent was posted from up
962 if (!internalMessage)
963 Strand_ScheduleAck( &handler->strand );
|
964 mike 1.1 }
965 }
966 }
967
968 /*
969 Processes incoming message, including:
970 - decoding message from batch
971 - invoking callback to process message
972
973 Parameters:
974 handler - pointer to received data
975 Returns:
976 it returns result if 'callback' with the followinf meaning:
977 MI_TRUE - to continue normal operations
978 MI_FALSE - to close connection
979 */
|
980 krisbash 1.4 static Protocol_CallbackResult _ProcessReceivedMessage(
981 ProtocolSocket* handler)
|
982 mike 1.1 {
983 MI_Result r;
984 Message* msg = 0;
|
985 krisbash 1.4 ProtocolBase* protocolBase = (ProtocolBase*)handler->base.data;
986 Protocol_CallbackResult ret = PRT_RETURN_FALSE;
|
987 mike 1.1
988 /* create a message from a batch */
989 r = MessageFromBatch(
990 handler->receivingBatch,
991 handler->recv_buffer.base.originalMessagePointer,
992 handler->recv_buffer.batchInfo,
993 handler->recv_buffer.base.pageCount,
|
994 krisbash 1.4 protocolBase->skipInstanceUnpack,
|
995 mike 1.1 &msg);
996
|
997 krisbash 1.4 if(MI_RESULT_OK != r)
998 {
999 trace_RestoreMessage_Failed(r, tcs(Result_ToString(r)));
1000 Batch_Destroy( handler->receivingBatch );
1001 }
1002
1003 /* clean up the state */
1004 handler->receivingBatch = 0;
1005 handler->receivingPageIndex = 0;
1006 memset(&handler->recv_buffer,0,sizeof(handler->recv_buffer));
1007
|
1008 mike 1.1 if (MI_RESULT_OK == r)
1009 {
|
1010 krisbash 1.4 trace_Socket_ReceivedMessage(
1011 msg,
1012 msg->tag,
1013 MessageName(msg->tag),
1014 msg->operationId );
|
1015 mike 1.1
1016 if (PRT_AUTH_OK != handler->authState)
1017 {
|
1018 krisbash 1.4 if( _ProcessAuthMessage(handler, msg) )
1019 ret = PRT_CONTINUE;
|
1020 mike 1.1 }
1021 else
1022 {
|
1023 krisbash 1.4 //disable receiving anything else until this message is ack'ed
1024 handler->base.mask &= ~SELECTOR_READ;
1025 // We cannot use Strand_SchedulePost becase we have to do
1026 // special treatment here (leave the strand in post)
1027 // We can use otherMsg to store this though
1028 Message_AddRef( msg ); // since the actual message use can be delayed
1029 handler->strand.info.otherMsg = msg;
1030 Strand_ScheduleAux( &handler->strand, PROTOCOLSOCKET_STRANDAUX_POSTMSG );
1031 ret = PRT_RETURN_TRUE;
|
1032 mike 1.1 }
1033
1034 Message_Release(msg);
1035 }
1036
1037 return ret;
1038 }
1039
1040 static Protocol_CallbackResult _ReadHeader(
|
1041 krisbash 1.4 ProtocolSocket* handler)
|
1042 mike 1.1 {
1043 char* buf;
1044 size_t buf_size, received;
1045 MI_Result r;
1046 MI_Uint32 index;
1047
1048 /* are we done with header? */
|
1049 krisbash 1.4 if (0 != handler->receivingPageIndex)
|
1050 mike 1.1 return PRT_CONTINUE;
1051
|
1052 krisbash 1.4 for ( ; ; )
|
1053 mike 1.1 {
1054 buf = (char*)&handler->recv_buffer;
1055 buf_size = (sizeof(HeaderBase) + sizeof(Header_BatchInfoItem) * handler->recv_buffer.base.pageCount);
1056 received = 0;
1057
1058 r = Sock_Read(handler->base.sock, buf + handler->receivedCurrentBlockBytes, buf_size - handler->receivedCurrentBlockBytes, &received);
1059
|
1060 krisbash 1.4 LOGD2((ZT("_ReadHeader - Read %lu bytes with result %d (%s)"), received, (int)r, mistrerror(r)));
|
1061 mike 1.1
1062 if ( r == MI_RESULT_OK && 0 == received )
|
1063 krisbash 1.4 {
1064 trace_Socket_ReadHeader_ConnectionClosed(handler);
1065 return PRT_RETURN_FALSE; /* connection closed */
1066 }
|
1067 mike 1.1
1068 if ( r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK )
|
1069 krisbash 1.4 {
1070 trace_Socket_ReadingHeader_Error(handler, r);
|
1071 mike 1.1 return PRT_RETURN_FALSE;
|
1072 krisbash 1.4 }
|
1073 mike 1.1
1074 if (!received)
1075 return PRT_RETURN_TRUE;
1076
1077 handler->receivedCurrentBlockBytes += received;
1078
1079 if (handler->receivedCurrentBlockBytes == buf_size)
1080 {
1081 /* got header - validate/allocate as required */
1082 if (handler->recv_buffer.base.pageCount > PROTOCOL_HEADER_MAX_PAGES)
|
1083 krisbash 1.4 {
1084 trace_Socket_ReadingHeader_ErrorPageCount(handler);
|
1085 mike 1.1 return PRT_RETURN_FALSE;
|
1086 krisbash 1.4 }
|
1087 mike 1.1
1088 if (handler->recv_buffer.base.magic != PROTOCOL_MAGIC)
|
1089 krisbash 1.4 {
1090 trace_Socket_ReadingHeader_ErrorMagic(handler);
|
1091 mike 1.1 return PRT_RETURN_FALSE;
|
1092 krisbash 1.4 }
|
1093 mike 1.1
1094 for (index =0; index < handler->recv_buffer.base.pageCount; index++)
1095 {
|
1096 krisbash 1.4 if (handler->recv_buffer.batchInfo[index].pageSize > MAX_ENVELOPE_SIZE)
1097 {
1098 trace_Socket_ReadingHeader_ErrorBatchSize(handler);
|
1099 mike 1.1 return PRT_RETURN_FALSE;
|
1100 krisbash 1.4 }
|
1101 mike 1.1 }
1102
1103 /* check if page info is also retrieved */
|
1104 krisbash 1.4 if (buf_size != ((sizeof(HeaderBase) + sizeof(Header_BatchInfoItem) * handler->recv_buffer.base.pageCount)))
|
1105 mike 1.1 continue;
1106
1107 /* create a batch */
1108 if (!Batch_CreateBatchByPageInfo(
|
1109 krisbash 1.4 &handler->receivingBatch,
|
1110 mike 1.1 handler->recv_buffer.batchInfo,
1111 handler->recv_buffer.base.pageCount))
|
1112 krisbash 1.4 {
1113 trace_Socket_ReadingHeader_ErrorCreatingBatch(handler);
|
1114 mike 1.1 return PRT_RETURN_FALSE;
|
1115 krisbash 1.4 }
|
1116 mike 1.1
1117 /* skip to next page */
1118 handler->receivingPageIndex++;
1119 handler->receivedCurrentBlockBytes = 0;
1120
1121 if ( (handler->receivingPageIndex - 1) == (int)handler->recv_buffer.base.pageCount )
1122 { /* received the whole message - process it */
|
1123 krisbash 1.4 return _ProcessReceivedMessage(handler);
|
1124 mike 1.1 }
1125 break;
1126 } /* if we read the whole buffer */
|
1127 krisbash 1.4 } /* for(;;) */
|
1128 mike 1.1 return PRT_CONTINUE;
1129 }
1130
1131 static Protocol_CallbackResult _ReadAllPages(
|
1132 krisbash 1.4 ProtocolSocket* handler)
|
1133 mike 1.1 {
1134 size_t received;
1135 MI_Result r;
1136 /* buffers to write */
1137 IOVec buffers[32];
1138 size_t counter;
1139
1140 /* are we done with header? - if not, return 'continue' */
|
1141 krisbash 1.4 if (0 == handler->receivingPageIndex)
|
1142 mike 1.1 return PRT_CONTINUE;
1143
1144
1145 for ( counter = 0; counter < MI_COUNT(buffers); counter++ )
1146 {
1147 const char* buf;
1148 MI_Uint32 index = (MI_Uint32)(handler->receivingPageIndex + counter);
1149
1150 buf = Batch_GetPageByIndex(handler->receivingBatch, index - 1);
|
1151 krisbash 1.4
|
1152 mike 1.1 if (!counter)
1153 buf += handler->receivedCurrentBlockBytes;
1154
1155 buffers[counter].ptr = (void*)buf;
1156 buffers[counter].len = handler->recv_buffer.batchInfo[index - 1].pageSize;
1157
1158 if (!counter)
1159 buffers[counter].len -= handler->receivedCurrentBlockBytes;
1160
|
1161 krisbash 1.4 if (index == handler->recv_buffer.base.pageCount)
|
1162 mike 1.1 {
1163 counter++;
1164 break;
1165 }
1166 }
1167
1168 received = 0;
1169
1170 r = Sock_ReadV(handler->base.sock, buffers, counter, &received);
1171
|
1172 krisbash 1.4 LOGD2((ZT("_ReadAllPages - Read %lu bytes with result %d (%s)"), received, (int)r, mistrerror(r)));
|
1173 mike 1.1
1174 if ( r == MI_RESULT_OK && 0 == received )
|
1175 krisbash 1.4 {
1176 trace_Socket_Read_ConnectionClosed(handler);
1177 return PRT_RETURN_FALSE; /* connection closed */
1178 }
|
1179 mike 1.1
1180 if ( r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK )
|
1181 krisbash 1.4 {
1182 trace_Socket_Read_Error(handler, r);
|
1183 mike 1.1 return PRT_RETURN_FALSE;
|
1184 krisbash 1.4 }
|
1185 mike 1.1
1186 if (!received)
1187 return PRT_RETURN_TRUE;
1188
1189 /* update index */
1190 for ( counter = 0; counter < MI_COUNT(buffers); counter++ )
1191 {
1192 if (!received)
1193 break;
1194
1195 if (received >= buffers[counter].len)
1196 {
1197 received -= buffers[counter].len;
1198 handler->receivingPageIndex++;
1199 handler->receivedCurrentBlockBytes = 0;
1200 continue;
1201 }
1202
1203 handler->receivedCurrentBlockBytes += received;
1204 break;
1205 }
1206 mike 1.1
1207 if ( (handler->receivingPageIndex - 1) == (int)handler->recv_buffer.base.pageCount )
1208 { /* received the whole message - process it */
|
1209 krisbash 1.4 return _ProcessReceivedMessage(handler);
|
1210 mike 1.1 }
1211
1212 return PRT_CONTINUE;
1213 }
1214
1215 static MI_Boolean _RequestCallbackRead(
|
1216 krisbash 1.4 ProtocolSocket* handler)
|
1217 mike 1.1 {
1218 int fullMessagesREceived = 0;
1219
1220 /* we have to keep repeating read until 'WOULD_BLOCK is returned;
1221 windows does not reset event until read buffer is empty */
1222 for (;fullMessagesREceived < 3;)
1223 {
1224 switch (_ReadHeader(handler))
1225 {
1226 case PRT_CONTINUE: break;
1227 case PRT_RETURN_TRUE: return MI_TRUE;
1228 case PRT_RETURN_FALSE: return MI_FALSE;
1229 }
1230
1231 switch (_ReadAllPages(handler))
1232 {
1233 case PRT_CONTINUE: break;
1234 case PRT_RETURN_TRUE: return MI_TRUE;
1235 case PRT_RETURN_FALSE: return MI_FALSE;
1236 }
1237 } /* for(;;)*/
1238 mike 1.1 return MI_TRUE;
1239 }
1240
1241 static MI_Boolean _RequestCallback(
1242 Selector* sel,
1243 Handler* handlerIn,
|
1244 krisbash 1.4 MI_Uint32 mask,
|
1245 mike 1.1 MI_Uint64 currentTimeUsec)
1246 {
|
1247 krisbash 1.4 ProtocolSocket* handler = (ProtocolSocket*)handlerIn;
1248 ProtocolBase* protocolBase = (ProtocolBase*)handler->base.data;
|
1249 mike 1.1
1250 MI_UNUSED(sel);
1251 MI_UNUSED(currentTimeUsec);
1252
1253 if (mask & SELECTOR_READ)
1254 {
1255 if (!_RequestCallbackRead(handler))
1256 {
|
1257 krisbash 1.4 trace_RequestCallbackRead_Failed( handler );
1258 if( !handler->isConnected && PRT_TYPE_CONNECTOR == protocolBase->type )
|
1259 mike 1.1 {
|
1260 krisbash 1.4 Strand_ScheduleAux( &handler->strand, PROTOCOLSOCKET_STRANDAUX_CONNECTEVENT );
|
1261 mike 1.1 }
1262 goto closeConnection;
1263 }
|
1264 krisbash 1.4 else
|
1265 mike 1.1 {
|
1266 krisbash 1.4 handler->isConnected = MI_TRUE;
1267 if( PRT_TYPE_CONNECTOR == protocolBase->type && PRT_AUTH_OK == handler->authState )
|
1268 mike 1.1 {
|
1269 krisbash 1.4 if( Atomic_Swap(&handler->connectEventSent, 1) == 0 )
1270 {
1271 trace_RequestCallback_Connect_OnFirstRead(handler);
1272 Strand_ScheduleAux( &handler->strand, PROTOCOLSOCKET_STRANDAUX_CONNECTEVENT );
1273 }
|
1274 mike 1.1 }
1275 }
1276 }
1277
1278 if (mask & SELECTOR_WRITE)
1279 {
1280 if (!_RequestCallbackWrite(handler))
1281 {
|
1282 krisbash 1.4 trace_RequestCallbackRead_Failed( handler );
|
1283 mike 1.1 goto closeConnection;
1284 }
|
1285 krisbash 1.4 else
|
1286 mike 1.1 {
|
1287 krisbash 1.4 if( !handler->isConnected )
|
1288 mike 1.1 {
|
1289 krisbash 1.4 handler->isConnected = MI_TRUE;
1290 if( PRT_TYPE_CONNECTOR == protocolBase->type && PRT_AUTH_OK == handler->authState )
1291 {
1292 if( Atomic_Swap(&handler->connectEventSent, 1) == 0 )
1293 {
1294 trace_RequestCallback_Connect_OnFirstWrite( handler );
1295 Strand_ScheduleAux( &handler->strand, PROTOCOLSOCKET_STRANDAUX_CONNECTEVENT );
1296 }
1297 }
|
1298 mike 1.1 }
1299 }
1300 }
1301
|
1302 krisbash 1.4 /* Close connection by timeout or error */
1303 if( (mask & SELECTOR_TIMEOUT) || (mask & SELECTOR_EXCEPTION) )
1304 {
1305 trace_RequestCallback_Connect_ClosingAfterMask( handler, mask );
1306 goto closeConnection;
1307 }
|
1308 mike 1.1
1309 if ((mask & SELECTOR_REMOVE) != 0 ||
1310 (mask & SELECTOR_DESTROY) != 0)
1311 {
|
1312 krisbash 1.4 trace_RequestCallback_Connect_RemovingHandler( handler, mask, handler->base.mask );
1313
1314 _ProtocolSocket_Cleanup(handler);
|
1315 mike 1.1
|
1316 krisbash 1.4 ProtocolSocket_Release(handler);
1317 }
|
1318 mike 1.1
|
1319 krisbash 1.4 return MI_TRUE;
|
1320 mike 1.1
|
1321 krisbash 1.4 closeConnection:
|
1322 mike 1.1
|
1323 krisbash 1.4 //release message and post ack if required
1324 if (handler->message)
1325 {
1326 MI_Boolean internalMessage = Message_IsInternalMessage( handler->message );
|
1327 mike 1.1
|
1328 krisbash 1.4 Message_Release(handler->message);
|
1329 mike 1.1 handler->message = 0;
1330
|
1331 krisbash 1.4 //ACK up if the message just sent was posted from up
1332 if (!internalMessage)
1333 Strand_ScheduleAck( &handler->strand );
|
1334 mike 1.1 }
1335
|
1336 krisbash 1.4 LOGD2((ZT("_RequestCallback - closed client connection")));
1337 trace_Socket_ClosingConnection( handler, mask );
|
1338 mike 1.1
1339 return MI_FALSE;
1340 }
1341
1342 static MI_Boolean _ListenerCallback(
1343 Selector* sel,
1344 Handler* handler,
|
1345 krisbash 1.4 MI_Uint32 mask,
|
1346 mike 1.1 MI_Uint64 currentTimeUsec)
1347 {
|
1348 krisbash 1.4 ProtocolBase* self = (ProtocolBase*)handler->data;
|
1349 mike 1.1 MI_Result r;
1350 Sock s;
1351 Addr addr;
|
1352 krisbash 1.4 ProtocolSocket* h;
|
1353 mike 1.1
|
1354 krisbash 1.4 MI_UNUSED(sel);
1355 MI_UNUSED(currentTimeUsec);
|
1356 mike 1.1
1357 if (mask & SELECTOR_READ)
1358 {
1359 /* Accept the incoming connection */
1360 r = Sock_Accept(handler->sock, &s, &addr);
1361
1362 if (MI_RESULT_WOULD_BLOCK == r)
1363 return MI_TRUE;
1364
1365 if (r != MI_RESULT_OK)
1366 {
|
1367 krisbash 1.4 trace_SockAccept_Failed(Sock_GetLastError());
|
1368 mike 1.1 return MI_TRUE;
1369 }
1370
1371 r = Sock_SetBlocking(s, MI_FALSE);
1372 if (r != MI_RESULT_OK)
1373 {
|
1374 krisbash 1.4 trace_SockSetBlocking_Failed();
|
1375 mike 1.1 Sock_Close(s);
1376 return MI_TRUE;
1377 }
1378
1379 /* Create handler */
|
1380 krisbash 1.4 h = _ProtocolSocket_Server_New(self,s);
|
1381 mike 1.1
1382 if (!h)
1383 {
1384 Sock_Close(s);
1385 return MI_TRUE;
1386 }
1387
|
1388 krisbash 1.4 Strand_Leave( &h->strand );
|
1389 mike 1.1
1390 /* Watch for read events on the incoming connection */
|
1391 krisbash 1.4 r = _AddProtocolSocket_Handler(self->selector, h);
|
1392 mike 1.1
1393 if (r != MI_RESULT_OK)
1394 {
|
1395 krisbash 1.4 ProtocolSocket_Release(h);
1396 trace_SelectorAddHandler_Failed();
|
1397 mike 1.1 return MI_TRUE;
1398 }
1399 }
1400
1401 if ((mask & SELECTOR_REMOVE) != 0 ||
1402 (mask & SELECTOR_DESTROY) != 0)
1403 {
1404 Sock_Close(handler->sock);
|
1405 krisbash 1.4 PAL_Free(handler);
|
1406 mike 1.1 }
1407
1408 return MI_TRUE;
1409 }
1410
1411 static MI_Result _CreateListener(
1412 Sock* s,
1413 const char* locator)
1414 {
1415 const char* posColon;
1416
1417 posColon = strchr(locator, ':');
1418
1419 if (!posColon)
1420 return Sock_CreateLocalListener(s, locator);
1421
1422 /* create listener for remote address like host:port or :port (ANYADDR) */
1423 {
1424 unsigned short port = (unsigned short)atol(posColon+1);
1425 char host[128];
1426 unsigned int len = (unsigned int)(posColon - locator);
1427 mike 1.1 Addr addr;
1428 MI_Result r;
1429
1430 if (len > 0)
1431 {
1432 if (len >= sizeof(host))
1433 return MI_RESULT_FAILED;
1434
1435 memcpy(host, locator, len);
1436 host[len] = 0;
1437
1438 // Initialize address.
|
1439 krisbash 1.4 r = Addr_Init(&addr, host, port, MI_FALSE);
|
1440 mike 1.1 if (r != MI_RESULT_OK)
1441 return MI_RESULT_FAILED;
1442 }
1443 else
1444 {
1445 Addr_InitAny(&addr, port);
1446 }
1447
1448 return Sock_CreateListener(s, &addr);
1449 }
1450 }
1451
1452 static MI_Result _CreateConnector(
1453 Sock* s,
1454 const char* locator)
1455 {
1456 const char* posColon;
1457
|
1458 krisbash 1.4 /* This function expects a locator in the form "_host_:_port_", for HTTP */
1459 /* connections, or in the form of a file name, for local connections */
1460 /* using a socket. In the latter case, the file name is the nsme of the */
1461 /* socket special file. Thus, socket special files used with this code */
1462 /* may not contain a colon in their names. Servers with IPv6 addresses */
1463 /* must use symbolic names, because IPv6 addresses use a colon as a separator */
1464
|
1465 mike 1.1 posColon = strchr(locator, ':');
1466 if (!posColon)
1467 return Sock_CreateLocalConnector(s, locator);
|
1468 krisbash 1.4 return Sock_CreateIPConnector(s, locator);
|
1469 mike 1.1 }
1470
|
1471 krisbash 1.4 static MI_Result _ProtocolBase_Init(
1472 _In_ ProtocolBase* self,
1473 _In_opt_ Selector* selector, /*optional, maybe NULL*/
1474 _In_opt_ OpenCallback callback,
1475 _In_opt_ void* callbackData,
1476 Protocol_Type protocolType)
|
1477 mike 1.1 {
1478 /* Check parameters */
|
1479 krisbash 1.4 if (!self)
|
1480 mike 1.1 return MI_RESULT_INVALID_PARAMETER;
1481
1482 if (selector)
1483 { /* attach the exisiting selector */
1484 self->selector = selector;
1485 self->internal_selector_used = MI_FALSE;
1486 }
1487 else
|
1488 krisbash 1.4 { /* create a new selector */
|
1489 mike 1.1 /* Initialize the network */
1490 Sock_Start();
1491
1492 /* Initialize the selector */
1493 if (Selector_Init(&self->internal_selector) != MI_RESULT_OK)
1494 {
1495 return MI_RESULT_FAILED;
1496 }
1497 self->selector = &self->internal_selector;
1498 self->internal_selector_used = MI_TRUE;
1499 }
1500
1501 /* Save the callback and callbackData */
1502 self->callback = callback;
1503 self->callbackData = callbackData;
|
1504 krisbash 1.4 self->skipInstanceUnpack = MI_FALSE;
1505 self->type = protocolType;
|
1506 mike 1.1
1507 /* Set the magic number */
1508 self->magic = _MAGIC;
1509
1510 return MI_RESULT_OK;
1511 }
1512
1513 /*
1514 **==============================================================================
1515 **
1516 ** Public definitions:
1517 **
1518 **==============================================================================
1519 */
1520
|
1521 krisbash 1.4 MI_Result ProtocolBase_New_Listener(
1522 _Out_ ProtocolBase** selfOut,
1523 _In_opt_ Selector* selector, /*optional, maybe NULL*/
1524 _In_ const char* locator,
1525 _In_ OpenCallback callback,
1526 _In_ void* callbackData)
|
1527 mike 1.1 {
|
1528 krisbash 1.4 ProtocolBase* self;
|
1529 mike 1.1 MI_Result r;
1530 Sock listener;
1531
|
1532 krisbash 1.4 /* Allocate structure */
1533 {
1534 self = (ProtocolBase*)PAL_Calloc(1, sizeof(ProtocolBase));
1535
1536 if (!self)
1537 return MI_RESULT_FAILED;
1538 }
1539
1540 r = _ProtocolBase_Init(self, selector, callback, callbackData, PRT_TYPE_LISTENER);
|
1541 mike 1.1
1542 if (MI_RESULT_OK != r)
|
1543 krisbash 1.4 {
1544 PAL_Free(self);
|
1545 mike 1.1 return r;
|
1546 krisbash 1.4 }
|
1547 mike 1.1
|
1548 krisbash 1.4 /* Set output parameter */
1549 *selfOut = self;
|
1550 mike 1.1
1551 /* Create listener socket */
1552 {
1553 r = _CreateListener(&listener, locator);
1554
1555 if (r != MI_RESULT_OK)
1556 {
|
1557 krisbash 1.4 ProtocolBase_Delete(self);
|
1558 mike 1.1 return r;
1559 }
1560
1561 r = Sock_SetBlocking(listener, MI_FALSE);
1562
1563 if (r != MI_RESULT_OK)
1564 {
1565 Sock_Close(listener);
|
1566 krisbash 1.4 ProtocolBase_Delete(self);
|
1567 mike 1.1 return r;
1568 }
1569 }
1570
1571 /* Watch for read events on the listener socket (client connections) */
1572 {
|
1573 krisbash 1.4 Handler* h = (Handler*)PAL_Calloc(1, sizeof(Handler));
|
1574 mike 1.1
1575 if (!h)
1576 {
1577 Sock_Close(listener);
|
1578 krisbash 1.4 ProtocolBase_Delete(self);
|
1579 mike 1.1 return MI_RESULT_FAILED;
1580 }
1581
1582 h->sock = listener;
1583 h->mask = SELECTOR_READ | SELECTOR_EXCEPTION;
1584 h->callback = _ListenerCallback;
1585 h->data = self;
1586
1587 r = Selector_AddHandler(self->selector, h);
1588
1589 if (r != MI_RESULT_OK)
1590 {
1591 Sock_Close(listener);
|
1592 krisbash 1.4 PAL_Free(h);
1593 ProtocolBase_Delete(self);
|
1594 mike 1.1 return r;
1595 }
1596 }
1597
1598 return MI_RESULT_OK;
1599 }
1600
|
1601 krisbash 1.4 MI_Result _ProtocolSocket_New(
1602 #if defined(STRAND_ENABLE_DEBUG)
1603 _In_ StrandDebugInfo debug,
1604 #endif
1605 _Out_ ProtocolSocket** selfOut,
1606 _In_opt_ InteractionOpenParams* params, // Only used on connector types
1607 size_t structSize) // if 0 then sizeof(ProtocolSocket) is assumed
1608 {
1609 ProtocolSocket* self;
1610
1611 DEBUG_ASSERT( 0 == structSize || structSize >= sizeof(ProtocolSocket) );
1612
1613 *selfOut = NULL;
1614
1615 if( 0 == structSize )
1616 structSize = sizeof(ProtocolSocket);
1617
1618 /* Allocate structure */
1619 {
1620 self = (ProtocolSocket*)PAL_Calloc(1, structSize);
1621
1622 krisbash 1.4 if (!self)
1623 return MI_RESULT_FAILED;
1624 }
1625
1626 Strand_Init( STRAND_PASSDEBUG(debug) &self->strand, &_ProtocolSocket_FT, STRAND_FLAG_ENTERSTRAND, params);
1627 self->refCount = 1; //ref associated with Strand. Released on Strand_Finish
1628 self->closeOtherScheduled = MI_FALSE;
1629
1630 self->base.callback = _RequestCallback;
1631
1632 /* Set output parameter */
1633 *selfOut = self;
1634 return MI_RESULT_OK;
1635 }
1636
1637 ProtocolSocket* _ProtocolSocket_Server_New(
1638 _In_ ProtocolBase * protocolBase,
1639 _In_ Sock sock )
1640 {
1641 ProtocolSocket* self = NULL;
1642
1643 krisbash 1.4 if( MI_RESULT_OK == _ProtocolSocket_New( STRAND_DEBUG(ProtocolSocketServer) &self, NULL, 0) )
1644 {
1645 self->base.data = protocolBase;
1646 self->base.sock = sock;
1647 self->base.mask = SELECTOR_READ | SELECTOR_EXCEPTION;
1648
1649 /* waiting for connect-request */
1650 self->authState = PRT_AUTH_WAIT_CONNECTION_REQUEST;
1651 }
1652
1653 return self;
1654 }
1655
1656 MI_Result _ProtocolSocketAndBase_New(
1657 #if defined(STRAND_ENABLE_DEBUG)
1658 _In_ StrandDebugInfo debug,
1659 #endif
1660 _Out_ ProtocolSocketAndBase** selfOut,
1661 _In_opt_ InteractionOpenParams* params, // Only used on connector types
1662 _In_opt_ Selector* selector, // optional, maybe NULL
1663 _In_opt_ OpenCallback callback, // only used on Agent
1664 krisbash 1.4 _In_opt_ void* callbackData, // used along with callback
1665 Protocol_Type protocolType)
|
1666 mike 1.1 {
|
1667 krisbash 1.4 ProtocolSocketAndBase* self;
|
1668 mike 1.1 MI_Result r;
1669
|
1670 krisbash 1.4 DEBUG_ASSERT( ( NULL != params && callback == NULL ) || ( NULL == params && callback != NULL ) );
1671
1672 *selfOut = NULL;
1673
1674 r = _ProtocolSocket_New( STRAND_PASSDEBUG(debug) (ProtocolSocket**)&self, params, sizeof( ProtocolSocketAndBase ) );
1675
1676 if( MI_RESULT_OK != r )
1677 return r;
1678
1679 r = _ProtocolBase_Init(&self->internalProtocolBase, selector, callback, callbackData, protocolType);
|
1680 mike 1.1
1681 if (MI_RESULT_OK != r)
|
1682 krisbash 1.4 {
1683 PAL_Free(self);
|
1684 mike 1.1 return r;
|
1685 krisbash 1.4 }
1686
1687 self->protocolSocket.base.data = &self->internalProtocolBase;
1688
1689 // ProtocolSocketAndBase objects need to delay wait until protocol run is done
1690 Strand_SetDelayFinish(&self->protocolSocket.strand);
1691
1692 Strand_Leave( &self->protocolSocket.strand );
1693
1694 // Set output parameter
1695 *selfOut = self;
1696 return MI_RESULT_OK;
1697 }
1698
1699 MI_Result ProtocolSocketAndBase_New_Connector(
1700 _Out_ ProtocolSocketAndBase** selfOut,
1701 _In_opt_ Selector* selector, // optional, maybe NULL
1702 _In_ const char* locator,
1703 _In_ InteractionOpenParams* params,
1704 _In_ const char* user,
1705 _In_ const char* password )
1706 krisbash 1.4 {
1707 ProtocolSocketAndBase* self;
1708 MI_Result r;
1709 Sock connector;
1710
1711 DEBUG_ASSERT( NULL != params && NULL != params->interaction && NULL == params->callbackData );
|
1712 mike 1.1
1713 *selfOut = 0;
1714
|
1715 krisbash 1.4 r = _ProtocolSocketAndBase_New( STRAND_DEBUG(ProtocolConnector) &self, params, selector, NULL, NULL, PRT_TYPE_CONNECTOR );
1716
1717 if( r != MI_RESULT_OK )
1718 return r;
|
1719 mike 1.1
1720 /* Create connector socket */
1721 {
1722 // Connect to server.
1723 r = _CreateConnector(&connector, locator);
1724 if (r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK)
1725 {
|
1726 krisbash 1.4 trace_SocketConnectorFailed(locator);
1727 _ProtocolSocketAndBase_Delete(self);
1728 return r;
|
1729 mike 1.1 }
1730 }
1731
|
1732 krisbash 1.4 /* setting connector's structure */
|
1733 mike 1.1 {
|
1734 krisbash 1.4 ProtocolSocket* h = &self->protocolSocket;
|
1735 mike 1.1
1736 h->base.sock = connector;
1737 h->base.mask = SELECTOR_READ | SELECTOR_WRITE | SELECTOR_EXCEPTION;
1738 h->authState = PRT_AUTH_WAIT_CONNECTION_RESPONSE;
1739
|
1740 krisbash 1.4 r = _AddProtocolSocket_Handler(self->internalProtocolBase.selector, h);
|
1741 mike 1.1
1742 if (r != MI_RESULT_OK)
1743 {
1744 Sock_Close(connector);
|
1745 krisbash 1.4 _ProtocolSocketAndBase_Delete(self);
1746 return r;
|
1747 mike 1.1 }
1748
1749 /* send connect request */
|
1750 krisbash 1.4 if( !_SendAuthRequest(h, user, password, NULL) )
|
1751 mike 1.1 {
|
1752 krisbash 1.4 // this will call _RequestCallback which will schedule a CloseOther,
1753 // but that is not going delete the object (since it is not even truly opened),
1754 // so do it explicitely
1755 Selector_RemoveHandler(self->internalProtocolBase.selector, &h->base);
1756 _ProtocolSocketAndBase_Delete(self);
|
1757 mike 1.1 return MI_RESULT_FAILED;
1758 }
1759 }
1760
1761 /* Set output parameter */
1762 *selfOut = self;
1763 return MI_RESULT_OK;
1764 }
1765
|
1766 krisbash 1.4 /*
1767 Creates a new protocol object from connected stream socket
1768 (typically a pipe from server to agent).
1769
1770 Parameters:
1771 self - [out] protocol object
1772 selector - [opt] selector to use for socket monitoring
1773 s - socket; if protocol created successfully, socket will be closed in Protocol_Delete.
1774 If operation failed, socket is not closed.
1775 skipInstanceUnpack - flag to skip instance un-packing; used
1776 to skip unpacking instances from agent
1777 callback - function that protocol calls to inform about new connection
1778 callbackData -
1779
1780 Returns:
1781 'OK' if succefful, error otherwise
1782 */
1783 MI_Result _ProtocolSocketAndBase_New_From_Socket(
1784 _Out_ ProtocolSocketAndBase** selfOut,
1785 _In_opt_ InteractionOpenParams* params, // Only used on connector type
1786 _In_opt_ Selector* selector, // optional, maybe NULL
1787 krisbash 1.4 _In_ Sock sock,
1788 MI_Boolean skipInstanceUnpack,
1789 _In_opt_ OpenCallback callback, // only used on Agent
1790 _In_opt_ void* callbackData) // used along with callback
|
1791 mike 1.1 {
|
1792 krisbash 1.4 ProtocolSocketAndBase* self;
|
1793 mike 1.1 MI_Result r;
1794
|
1795 krisbash 1.4 *selfOut = 0;
1796
1797 r = _ProtocolSocketAndBase_New( STRAND_DEBUG(ProtocolFromSocket) &self, params, selector, callback, callbackData, PRT_TYPE_FROM_SOCKET );
|
1798 mike 1.1
|
1799 krisbash 1.4 if( r != MI_RESULT_OK )
|
1800 mike 1.1 return r;
1801
|
1802 krisbash 1.4 self->internalProtocolBase.skipInstanceUnpack = skipInstanceUnpack;
|
1803 mike 1.1
|
1804 krisbash 1.4 /* setup provided socket */
|
1805 mike 1.1 {
|
1806 krisbash 1.4 ProtocolSocket* h = &self->protocolSocket;
|
1807 mike 1.1
|
1808 krisbash 1.4 h->base.sock = sock;
|
1809 mike 1.1 h->base.mask = SELECTOR_READ | SELECTOR_EXCEPTION;
1810
1811 if (skipInstanceUnpack)
1812 {
1813 /* skipInstanceUnpack indicates that call made from server
1814 and socket connected to the agent
1815 In that case we can use back=pressure feature and
1816 ignore socket operations under stress */
|
1817 krisbash 1.4 //no more used - as flow control is implemented in protocol and wsman layers
1818 //h->base.mask |= SELECTOR_IGNORE_READ_OVERLOAD;
|
1819 mike 1.1 }
1820
1821 h->isConnected = MI_TRUE;
|
1822 krisbash 1.4 /* skip authentication for established connections
|
1823 mike 1.1 (only used in server/agent communication) */
1824 h->authState = PRT_AUTH_OK;
1825
|
1826 krisbash 1.4 r = _AddProtocolSocket_Handler(self->internalProtocolBase.selector, h);
|
1827 mike 1.1
1828 if (r != MI_RESULT_OK)
1829 {
|
1830 krisbash 1.4 _ProtocolSocketAndBase_Delete(self);
1831 return r;
|
1832 mike 1.1 }
1833 }
1834
1835 /* Set output parameter */
1836 *selfOut = self;
1837 return MI_RESULT_OK;
1838 }
1839
|
1840 krisbash 1.4 MI_Result ProtocolSocketAndBase_New_AgentConnector(
1841 _Out_ ProtocolSocketAndBase** selfOut,
1842 _In_opt_ Selector* selector, // optional, maybe NULL
1843 _In_ Sock s,
1844 _In_ InteractionOpenParams* params )
1845 {
1846 return _ProtocolSocketAndBase_New_From_Socket( selfOut, params, selector, s, MI_TRUE, NULL, NULL );
1847 }
1848
1849 MI_Result ProtocolSocketAndBase_New_Agent(
1850 _Out_ ProtocolSocketAndBase** selfOut,
1851 _In_opt_ Selector* selector, // optional, maybe NULL
1852 _In_ Sock s,
1853 _In_ OpenCallback callback,
1854 _In_ void* callbackData) // used along with callback
1855 {
1856 return _ProtocolSocketAndBase_New_From_Socket( selfOut, NULL, selector, s, MI_FALSE, callback, callbackData );
1857 }
1858
1859 MI_Result _ProtocolBase_Finish(
1860 ProtocolBase* self)
|
1861 mike 1.1 {
1862 /* Check parameters */
1863 if (!self)
1864 return MI_RESULT_INVALID_PARAMETER;
1865
1866 /* Check magic number */
1867 if (self->magic != _MAGIC)
1868 return MI_RESULT_INVALID_PARAMETER;
1869
1870 if (self->internal_selector_used)
1871 {
1872 /* Release selector;
1873 Note: selector-destory closes all sockects in a list including connector and listener */
1874 Selector_Destroy(self->selector);
1875
1876 /* Shutdown the network */
1877 Sock_Stop();
1878 }
1879
1880 /* Clear magic number */
1881 self->magic = 0xDDDDDDDD;
1882 mike 1.1
|
1883 krisbash 1.4 return MI_RESULT_OK;
1884 }
1885
1886 MI_Result ProtocolBase_Delete(
1887 ProtocolBase* self)
1888 {
1889 MI_Result r = _ProtocolBase_Finish( self );
1890
1891 if( MI_RESULT_OK != r )
1892 return r;
1893
|
1894 mike 1.1 /* Free self pointer */
|
1895 krisbash 1.4 PAL_Free(self);
|
1896 mike 1.1
|
1897 krisbash 1.4 return MI_RESULT_OK;
1898 }
1899
1900 MI_Result _ProtocolSocketAndBase_Delete(
1901 ProtocolSocketAndBase* self)
1902 {
1903 MI_Result r = _ProtocolBase_Finish( &self->internalProtocolBase );
1904
1905 if( MI_RESULT_OK != r )
1906 return r;
1907
1908 /* Free self pointer */
1909 PAL_Free(self);
|
1910 mike 1.1
1911 return MI_RESULT_OK;
1912 }
1913
1914 MI_Result Protocol_Run(
|
1915 krisbash 1.4 ProtocolBase* self,
|
1916 mike 1.1 MI_Uint64 timeoutUsec)
1917 {
1918 /* Run the selector */
|
1919 krisbash 1.4 return Selector_Run(self->selector, timeoutUsec, MI_FALSE);
|
1920 mike 1.1 }
1921
1922 static MI_Result _SendIN_IO_thread(
|
1923 krisbash 1.4 ProtocolBase* self,
1924 ProtocolSocket* sendSock,
|
1925 mike 1.1 Message* message)
1926 {
1927 /* check params */
1928 if (!self || !message )
1929 return MI_RESULT_INVALID_PARAMETER;
1930
1931 if (self->magic != _MAGIC)
1932 {
|
1933 krisbash 1.4 trace_Message_InvalidMagic();
|
1934 mike 1.1 return MI_RESULT_INVALID_PARAMETER;
1935 }
1936
1937 /* validate handler */
|
1938 krisbash 1.4 if (!sendSock || INVALID_SOCK == sendSock->base.sock)
|
1939 mike 1.1 {
|
1940 krisbash 1.4 trace_Message_ExpiredHandler(sendSock);
|
1941 mike 1.1
1942 return MI_RESULT_FAILED;
1943 }
1944
|
1945 krisbash 1.4 DEBUG_ASSERT(sendSock->message == NULL);
1946 sendSock->message = message;
|
1947 mike 1.1 Message_AddRef(message);
1948
1949 _PrepareMessageForSending(sendSock);
|
1950 krisbash 1.4
1951 if( !_RequestCallbackWrite(sendSock) && PRT_TYPE_LISTENER == self->type )
|
1952 mike 1.1 {
|
1953 krisbash 1.4 trace_QueueOverflowOrConnectionAbort(sendSock);
1954 return MI_RESULT_FAILED;
|
1955 mike 1.1 }
1956
1957 return MI_RESULT_OK;
1958 }
|