jens@0
|
1 |
//
|
jens@0
|
2 |
// BLIPFrameWriter.m
|
jens@0
|
3 |
// MYNetwork
|
jens@0
|
4 |
//
|
jens@0
|
5 |
// Created by Jens Alfke on 5/18/08.
|
jens@0
|
6 |
// Copyright 2008 Jens Alfke. All rights reserved.
|
jens@0
|
7 |
//
|
jens@0
|
8 |
|
jens@0
|
9 |
#import "BLIPReader.h"
|
jens@0
|
10 |
#import "BLIPWriter.h"
|
jens@0
|
11 |
#import "BLIP_Internal.h"
|
jens@0
|
12 |
|
jens@0
|
13 |
|
jens@0
|
14 |
#define kDefaultFrameSize 4096
|
jens@0
|
15 |
|
jens@0
|
16 |
|
jens@0
|
17 |
@implementation BLIPWriter
|
jens@0
|
18 |
|
jens@0
|
19 |
|
jens@0
|
20 |
- (void) dealloc
|
jens@0
|
21 |
{
|
jens@0
|
22 |
[_outBox release];
|
jens@0
|
23 |
[super dealloc];
|
jens@0
|
24 |
}
|
jens@0
|
25 |
|
jens@0
|
26 |
- (void) disconnect
|
jens@0
|
27 |
{
|
jens@0
|
28 |
[_outBox makeObjectsPerformSelector: @selector(_connectionClosed) withObject: nil];
|
jens@0
|
29 |
setObj(&_outBox,nil);
|
jens@0
|
30 |
[super disconnect];
|
jens@0
|
31 |
}
|
jens@0
|
32 |
|
jens@0
|
33 |
@synthesize numQueriesSent=_numQueriesSent;
|
jens@0
|
34 |
|
jens@0
|
35 |
|
jens@0
|
36 |
- (BOOL) isBusy
|
jens@0
|
37 |
{
|
jens@0
|
38 |
return _outBox.count>0 || [super isBusy];
|
jens@0
|
39 |
}
|
jens@0
|
40 |
|
jens@0
|
41 |
|
jens@0
|
42 |
- (void) _queueMessage: (BLIPMessage*)msg isNew: (BOOL)isNew
|
jens@0
|
43 |
{
|
jens@0
|
44 |
int n = _outBox.count, index;
|
jens@0
|
45 |
if( msg.urgent && n > 1 ) {
|
jens@0
|
46 |
// High-priority gets queued after the last existing high-priority message,
|
jens@0
|
47 |
// leaving one regular-priority message in between if possible.
|
jens@0
|
48 |
for( index=n-1; index>0; index-- ) {
|
jens@0
|
49 |
BLIPMessage *otherMsg = [_outBox objectAtIndex: index];
|
jens@0
|
50 |
if( [otherMsg urgent] ) {
|
jens@0
|
51 |
index = MIN(index+2, n);
|
jens@0
|
52 |
break;
|
jens@0
|
53 |
} else if( isNew && otherMsg._bytesWritten==0 ) {
|
jens@0
|
54 |
// But have to keep message starts in order
|
jens@0
|
55 |
index = index+1;
|
jens@0
|
56 |
break;
|
jens@0
|
57 |
}
|
jens@0
|
58 |
}
|
jens@0
|
59 |
if( index==0 )
|
jens@0
|
60 |
index = 1;
|
jens@0
|
61 |
} else {
|
jens@0
|
62 |
// Regular priority goes at the end of the queue:
|
jens@0
|
63 |
index = n;
|
jens@0
|
64 |
}
|
jens@0
|
65 |
if( ! _outBox )
|
jens@0
|
66 |
_outBox = [[NSMutableArray alloc] init];
|
jens@0
|
67 |
[_outBox insertObject: msg atIndex: index];
|
jens@0
|
68 |
|
jens@0
|
69 |
if( isNew ) {
|
jens@0
|
70 |
LogTo(BLIP,@"%@ queuing outgoing %@ at index %i",self,msg,index);
|
jens@0
|
71 |
if( n==0 )
|
jens@0
|
72 |
[self queueIsEmpty];
|
jens@0
|
73 |
}
|
jens@0
|
74 |
}
|
jens@0
|
75 |
|
jens@0
|
76 |
|
jens@0
|
77 |
- (BOOL) sendMessage: (BLIPMessage*)message
|
jens@0
|
78 |
{
|
jens@0
|
79 |
if( _shouldClose ) {
|
jens@0
|
80 |
Warn(@"%@: Attempt to send a message after the connection has started closing",self);
|
jens@0
|
81 |
return NO;
|
jens@0
|
82 |
}
|
jens@0
|
83 |
Assert(!message.sent,@"message has already been sent");
|
jens@0
|
84 |
[self _queueMessage: message isNew: YES];
|
jens@0
|
85 |
return YES;
|
jens@0
|
86 |
}
|
jens@0
|
87 |
|
jens@0
|
88 |
|
jens@0
|
89 |
- (BOOL) sendRequest: (BLIPRequest*)q response: (BLIPResponse*)response
|
jens@0
|
90 |
{
|
jens@0
|
91 |
if( !_shouldClose ) {
|
jens@0
|
92 |
[q _assignedNumber: ++_numQueriesSent];
|
jens@0
|
93 |
if( response ) {
|
jens@0
|
94 |
[response _assignedNumber: _numQueriesSent];
|
jens@0
|
95 |
[(BLIPReader*)self.reader _addPendingResponse: response];
|
jens@0
|
96 |
}
|
jens@0
|
97 |
}
|
jens@0
|
98 |
return [self sendMessage: q];
|
jens@0
|
99 |
}
|
jens@0
|
100 |
|
jens@0
|
101 |
|
jens@0
|
102 |
- (void) queueIsEmpty
|
jens@0
|
103 |
{
|
jens@0
|
104 |
if( _outBox.count > 0 ) {
|
jens@0
|
105 |
// Pop first message in queue:
|
jens@0
|
106 |
BLIPMessage *msg = [[_outBox objectAtIndex: 0] retain];
|
jens@0
|
107 |
[_outBox removeObjectAtIndex: 0];
|
jens@0
|
108 |
|
jens@0
|
109 |
// As an optimization, allow message to send a big frame unless there's a higher-priority
|
jens@0
|
110 |
// message right behind it:
|
jens@0
|
111 |
size_t frameSize = kDefaultFrameSize;
|
jens@0
|
112 |
if( msg.urgent || _outBox.count==0 || ! [[_outBox objectAtIndex: 0] urgent] )
|
jens@0
|
113 |
frameSize *= 4;
|
jens@0
|
114 |
|
jens@0
|
115 |
if( [msg _writeFrameTo: self maxSize: frameSize] ) {
|
jens@0
|
116 |
// add it back so it can send its next frame later:
|
jens@0
|
117 |
[self _queueMessage: msg isNew: NO];
|
jens@0
|
118 |
}
|
jens@0
|
119 |
[msg release];
|
jens@0
|
120 |
} else {
|
jens@0
|
121 |
LogTo(BLIPVerbose,@"%@: no more work for writer",self);
|
jens@0
|
122 |
}
|
jens@0
|
123 |
}
|
jens@0
|
124 |
|
jens@0
|
125 |
|
jens@0
|
126 |
|
jens@0
|
127 |
@end
|
jens@0
|
128 |
|
jens@0
|
129 |
|
jens@0
|
130 |
/*
|
jens@0
|
131 |
Copyright (c) 2008, Jens Alfke <jens@mooseyard.com>. All rights reserved.
|
jens@0
|
132 |
|
jens@0
|
133 |
Redistribution and use in source and binary forms, with or without modification, are permitted
|
jens@0
|
134 |
provided that the following conditions are met:
|
jens@0
|
135 |
|
jens@0
|
136 |
* Redistributions of source code must retain the above copyright notice, this list of conditions
|
jens@0
|
137 |
and the following disclaimer.
|
jens@0
|
138 |
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
jens@0
|
139 |
and the following disclaimer in the documentation and/or other materials provided with the
|
jens@0
|
140 |
distribution.
|
jens@0
|
141 |
|
jens@0
|
142 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
jens@0
|
143 |
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
jens@0
|
144 |
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
|
jens@0
|
145 |
BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
jens@0
|
146 |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
jens@0
|
147 |
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
jens@0
|
148 |
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
jens@0
|
149 |
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
jens@0
|
150 |
*/
|