trema 0.4.5 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +4 -4
- data/Guardfile +8 -0
- data/Rakefile +2 -1
- data/bin/trema +4 -0
- data/cruise.rb +1 -1
- data/features/core/switch_manager.feature +2 -2
- data/features/examples/message.vendor-action.feature +2 -2
- data/features/examples/message.vendor-stats-request.feature +20 -0
- data/features/trema_commands/kill.feature +4 -0
- data/features/trema_commands/killall.feature +1 -0
- data/features/trema_commands/run.feature +20 -1
- data/ruby/trema/command/run.rb +4 -0
- data/ruby/trema/default_openflow_channel_port.rb +26 -0
- data/ruby/trema/dsl/configuration.rb +2 -1
- data/ruby/trema/open-vswitch.rb +2 -4
- data/ruby/trema/stats-reply.c +10 -1
- data/ruby/trema/stats-request.c +34 -1
- data/ruby/trema/vendor-stats-reply.rb +6 -2
- data/ruby/trema/version.rb +1 -1
- data/spec/trema/dsl/runner_spec.rb +1 -1
- data/spec/trema/dsl/syntax_spec.rb +1 -1
- data/spec/trema/shell/vswitch_spec.rb +1 -1
- data/spec/trema/stats-reply_spec.rb +2 -1
- data/spec/trema/stats-request_spec.rb +11 -0
- data/src/examples/cbench_switch/cbench-switch.rb +1 -0
- data/src/examples/cbench_switch/cbench_switch.c +1 -1
- data/src/examples/openflow_message/vendor-action.rb +4 -4
- data/src/examples/openflow_message/vendor-stats-request.rb +66 -0
- data/src/examples/simple_router/arp-table.rb +6 -17
- data/src/examples/simple_router/interface.rb +20 -29
- data/src/examples/simple_router/routing-table.rb +15 -22
- data/src/examples/simple_router/simple-router.rb +75 -64
- data/src/lib/chibach.c +3 -2
- data/src/lib/event_handler.c +55 -23
- data/src/lib/event_handler.h +0 -5
- data/src/lib/external_callback.c +126 -0
- data/src/lib/external_callback.h +46 -0
- data/src/lib/messenger.c +58 -35
- data/src/lib/openflow_message.c +32 -11
- data/src/lib/trema.c +13 -7
- data/src/lib/trema.h +1 -0
- data/src/lib/utility.c +13 -2
- data/src/switch_manager/secure_channel_receiver.c +6 -1
- data/src/switch_manager/switch.c +27 -26
- data/src/switch_manager/switch_manager.c +31 -10
- data/src/tremashark/packet_capture.c +3 -2
- data/src/tremashark/tremashark.c +2 -2
- data/trema.gemspec +1 -1
- data/unittests/lib/external_callback_test.c +282 -0
- data/unittests/lib/messenger_test.c +22 -0
- data/unittests/lib/openflow_message_test.c +1 -1
- data/unittests/lib/trema_test.c +1 -1
- data/unittests/switch_manager/switch_manager_test.c +3 -3
- metadata +12 -6
- data/src/examples/simple_router/router-utils.rb +0 -211
data/src/lib/chibach.c
CHANGED
@@ -33,6 +33,7 @@
|
|
33
33
|
#include <unistd.h>
|
34
34
|
#include "chibach.h"
|
35
35
|
#include "chibach_private.h"
|
36
|
+
#include "external_callback.h"
|
36
37
|
#include "daemon.h"
|
37
38
|
#include "doubly_linked_list.h"
|
38
39
|
#include "log.h"
|
@@ -191,7 +192,7 @@ parse_argv( int *argc, char ***argv ) {
|
|
191
192
|
|
192
193
|
run_as_daemon = false;
|
193
194
|
controller.ip = 0x7f000001;
|
194
|
-
controller.port =
|
195
|
+
controller.port = 6653;
|
195
196
|
|
196
197
|
for ( int i = 0; i < *argc; ++i ) {
|
197
198
|
new_argv[ i ] = ( *argv )[ i ];
|
@@ -286,7 +287,7 @@ set_exit_handler() {
|
|
286
287
|
|
287
288
|
static void
|
288
289
|
set_dump_stats_as_external_callback() {
|
289
|
-
|
290
|
+
push_external_callback( dump_stats );
|
290
291
|
}
|
291
292
|
|
292
293
|
|
data/src/lib/event_handler.c
CHANGED
@@ -23,6 +23,7 @@
|
|
23
23
|
#include <unistd.h>
|
24
24
|
#include "checks.h"
|
25
25
|
#include "event_handler.h"
|
26
|
+
#include "external_callback.h"
|
26
27
|
#include "log.h"
|
27
28
|
#include "timer.h"
|
28
29
|
|
@@ -61,6 +62,30 @@ extern bool mock_add_periodic_event_callback( const time_t seconds, void ( *call
|
|
61
62
|
#define execute_timer_events mock_execute_timer_events
|
62
63
|
extern void mock_execute_timer_events( int *next_timeout_usec );
|
63
64
|
|
65
|
+
#ifdef init_external_callback
|
66
|
+
#undef init_external_callback
|
67
|
+
#endif
|
68
|
+
#define init_external_callback mock_init_external_callback
|
69
|
+
extern void mock_init_external_callback( void );
|
70
|
+
|
71
|
+
#ifdef finalize_external_callback
|
72
|
+
#undef finalize_external_callback
|
73
|
+
#endif
|
74
|
+
#define finalize_external_callback mock_finalize_external_callback
|
75
|
+
extern void mock_finalize_external_callback( void );
|
76
|
+
|
77
|
+
#ifdef push_external_callback
|
78
|
+
#undef push_external_callback
|
79
|
+
#endif
|
80
|
+
#define push_external_callback mock_push_external_callback
|
81
|
+
extern void mock_push_external_callback( external_callback_t callback );
|
82
|
+
|
83
|
+
#ifdef run_external_callback
|
84
|
+
#undef run_external_callback
|
85
|
+
#endif
|
86
|
+
#define run_external_callback mock_run_external_callback
|
87
|
+
extern void mock_run_external_callback( void );
|
88
|
+
|
64
89
|
#endif // UNIT_TESTING
|
65
90
|
|
66
91
|
|
@@ -94,19 +119,19 @@ fd_set current_write_set;
|
|
94
119
|
|
95
120
|
int fd_set_size = 0;
|
96
121
|
|
97
|
-
external_callback_t external_callback = ( external_callback_t ) NULL;
|
98
|
-
|
99
|
-
|
100
122
|
static void
|
101
123
|
_init_event_handler() {
|
102
124
|
event_last = event_list;
|
103
|
-
event_handler_state = EVENT_HANDLER_INITIALIZED;
|
104
125
|
|
105
126
|
memset( event_list, 0, sizeof( event_fd ) * FD_SETSIZE );
|
106
127
|
memset( event_fd_set, 0, sizeof( event_fd * ) * FD_SETSIZE );
|
107
128
|
|
108
129
|
FD_ZERO( &event_read_set );
|
109
130
|
FD_ZERO( &event_write_set );
|
131
|
+
|
132
|
+
init_external_callback();
|
133
|
+
|
134
|
+
event_handler_state = EVENT_HANDLER_INITIALIZED;
|
110
135
|
}
|
111
136
|
void ( *init_event_handler )() = _init_event_handler;
|
112
137
|
|
@@ -120,18 +145,15 @@ _finalize_event_handler() {
|
|
120
145
|
}
|
121
146
|
|
122
147
|
event_handler_state = EVENT_HANDLER_FINALIZED;
|
148
|
+
|
149
|
+
finalize_external_callback();
|
123
150
|
}
|
124
151
|
void ( *finalize_event_handler )() = _finalize_event_handler;
|
125
152
|
|
126
153
|
|
127
154
|
static bool
|
128
155
|
_run_event_handler_once( int timeout_usec ) {
|
129
|
-
|
130
|
-
external_callback_t callback = external_callback;
|
131
|
-
external_callback = NULL;
|
132
|
-
|
133
|
-
callback();
|
134
|
-
}
|
156
|
+
run_external_callback();
|
135
157
|
|
136
158
|
memcpy( ¤t_read_set, &event_read_set, sizeof( fd_set ) );
|
137
159
|
memcpy( ¤t_write_set, &event_write_set, sizeof( fd_set ) );
|
@@ -143,6 +165,7 @@ _run_event_handler_once( int timeout_usec ) {
|
|
143
165
|
|
144
166
|
if ( set_count == -1 ) {
|
145
167
|
if ( errno == EINTR ) {
|
168
|
+
run_external_callback();
|
146
169
|
return true;
|
147
170
|
}
|
148
171
|
error( "Failed to select ( errno = %s [%d] ).", strerror( errno ), errno );
|
@@ -151,11 +174,13 @@ _run_event_handler_once( int timeout_usec ) {
|
|
151
174
|
}
|
152
175
|
else if ( set_count == 0 ) {
|
153
176
|
// timed out
|
177
|
+
run_external_callback();
|
154
178
|
return true;
|
155
179
|
}
|
156
180
|
|
157
|
-
|
181
|
+
run_external_callback();
|
158
182
|
|
183
|
+
event_fd *event_itr = event_list;
|
159
184
|
while ( event_itr < event_last ) {
|
160
185
|
event_fd current_event = *event_itr;
|
161
186
|
|
@@ -163,6 +188,23 @@ _run_event_handler_once( int timeout_usec ) {
|
|
163
188
|
current_event.write_callback( current_event.fd, current_event.write_data );
|
164
189
|
}
|
165
190
|
|
191
|
+
// In the rare cases the current fd is closed, a new one is opened
|
192
|
+
// with the same fd and is put in the same location we can just
|
193
|
+
// wait for the next select call.
|
194
|
+
if ( current_event.fd == event_itr->fd ) {
|
195
|
+
event_itr = event_itr + 1;
|
196
|
+
}
|
197
|
+
else {
|
198
|
+
debug( "run_event_handler_once: event fd is changed ( current = %d, new = %d )", current_event.fd, event_itr->fd );
|
199
|
+
}
|
200
|
+
}
|
201
|
+
|
202
|
+
run_external_callback();
|
203
|
+
|
204
|
+
event_itr = event_list;
|
205
|
+
while ( event_itr < event_last ) {
|
206
|
+
event_fd current_event = *event_itr;
|
207
|
+
|
166
208
|
if ( FD_ISSET( current_event.fd, ¤t_read_set ) ) {
|
167
209
|
current_event.read_callback( current_event.fd, current_event.read_data );
|
168
210
|
}
|
@@ -178,6 +220,8 @@ _run_event_handler_once( int timeout_usec ) {
|
|
178
220
|
}
|
179
221
|
}
|
180
222
|
|
223
|
+
run_external_callback();
|
224
|
+
|
181
225
|
return true;
|
182
226
|
}
|
183
227
|
bool ( *run_event_handler_once )( int ) = _run_event_handler_once;
|
@@ -367,18 +411,6 @@ _writable( int fd ) {
|
|
367
411
|
bool ( *writable )( int fd ) = _writable;
|
368
412
|
|
369
413
|
|
370
|
-
static bool
|
371
|
-
_set_external_callback( external_callback_t callback ) {
|
372
|
-
if ( external_callback != NULL ) {
|
373
|
-
return false;
|
374
|
-
}
|
375
|
-
|
376
|
-
external_callback = callback;
|
377
|
-
return true;
|
378
|
-
}
|
379
|
-
bool ( *set_external_callback )( external_callback_t callback ) = _set_external_callback;
|
380
|
-
|
381
|
-
|
382
414
|
/*
|
383
415
|
* Local variables:
|
384
416
|
* c-basic-offset: 2
|
data/src/lib/event_handler.h
CHANGED
@@ -27,7 +27,6 @@
|
|
27
27
|
|
28
28
|
|
29
29
|
typedef void ( *event_fd_callback )( int, void *data );
|
30
|
-
typedef void ( *external_callback_t )( void );
|
31
30
|
|
32
31
|
extern void ( *init_event_handler )();
|
33
32
|
extern void ( *finalize_event_handler )();
|
@@ -46,10 +45,6 @@ extern void ( *set_writable )( int fd, bool state );
|
|
46
45
|
extern bool ( *readable )( int fd );
|
47
46
|
extern bool ( *writable )( int fd );
|
48
47
|
|
49
|
-
// Optional functions for event handlers to implement, must be signal
|
50
|
-
// safe. Leave as NULL if not supported.
|
51
|
-
extern bool ( *set_external_callback )( external_callback_t callback );
|
52
|
-
|
53
48
|
|
54
49
|
#endif // EVENT_HANDLER_H
|
55
50
|
|
@@ -0,0 +1,126 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) 2013 NEC Corporation
|
3
|
+
*
|
4
|
+
* This program is free software; you can redistribute it and/or modify
|
5
|
+
* it under the terms of the GNU General Public License, version 2, as
|
6
|
+
* published by the Free Software Foundation.
|
7
|
+
*
|
8
|
+
* This program is distributed in the hope that it will be useful,
|
9
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
* GNU General Public License for more details.
|
12
|
+
*
|
13
|
+
* You should have received a copy of the GNU General Public License along
|
14
|
+
* with this program; if not, write to the Free Software Foundation, Inc.,
|
15
|
+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
16
|
+
*/
|
17
|
+
|
18
|
+
|
19
|
+
#include <assert.h>
|
20
|
+
#include "external_callback.h"
|
21
|
+
#include "log.h"
|
22
|
+
#include "wrapper.h"
|
23
|
+
|
24
|
+
#ifdef UNIT_TESTING
|
25
|
+
|
26
|
+
#ifdef xcalloc
|
27
|
+
#undef xcalloc
|
28
|
+
#endif
|
29
|
+
#define xcalloc mock_xcalloc
|
30
|
+
extern void *mock_xcalloc( size_t nmemb, size_t size );
|
31
|
+
|
32
|
+
#ifdef xfree
|
33
|
+
#undef xfree
|
34
|
+
#endif
|
35
|
+
#define xfree mock_xfree
|
36
|
+
extern void mock_xfree( void *ptr );
|
37
|
+
|
38
|
+
#ifdef debug
|
39
|
+
#undef debug
|
40
|
+
#endif
|
41
|
+
#define debug mock_debug
|
42
|
+
extern void mock_debug( const char *format, ... );
|
43
|
+
|
44
|
+
#define static
|
45
|
+
|
46
|
+
#endif // UNIT_TESTING
|
47
|
+
|
48
|
+
|
49
|
+
typedef struct {
|
50
|
+
external_callback_t *buffer;
|
51
|
+
unsigned int size;
|
52
|
+
unsigned int write_position;
|
53
|
+
unsigned int read_position;
|
54
|
+
} ring_buffer;
|
55
|
+
|
56
|
+
static const unsigned int MAX_EXTERNAL_CALLBACK = 16;
|
57
|
+
static ring_buffer *external_callbacks = NULL;
|
58
|
+
|
59
|
+
|
60
|
+
static void
|
61
|
+
_init_external_callback() {
|
62
|
+
assert( external_callbacks == NULL );
|
63
|
+
|
64
|
+
external_callbacks = xcalloc( 1, sizeof( ring_buffer ) );
|
65
|
+
external_callbacks->buffer = xcalloc( MAX_EXTERNAL_CALLBACK, sizeof( external_callback_t * ) );
|
66
|
+
external_callbacks->size = MAX_EXTERNAL_CALLBACK;
|
67
|
+
}
|
68
|
+
void ( *init_external_callback )() = _init_external_callback;
|
69
|
+
|
70
|
+
|
71
|
+
static void
|
72
|
+
_finalize_external_callback() {
|
73
|
+
assert( external_callbacks != NULL );
|
74
|
+
assert( external_callbacks->buffer != NULL );
|
75
|
+
|
76
|
+
xfree( external_callbacks->buffer );
|
77
|
+
xfree( external_callbacks );
|
78
|
+
external_callbacks = NULL;
|
79
|
+
}
|
80
|
+
void ( *finalize_external_callback )() = _finalize_external_callback;
|
81
|
+
|
82
|
+
|
83
|
+
static bool
|
84
|
+
_push_external_callback( external_callback_t callback ) {
|
85
|
+
if ( callback == NULL ) {
|
86
|
+
return false;
|
87
|
+
}
|
88
|
+
if ( external_callbacks == NULL ) {
|
89
|
+
return false;
|
90
|
+
}
|
91
|
+
assert( external_callbacks->buffer != NULL );
|
92
|
+
|
93
|
+
debug( "push_external_callback: %p", callback );
|
94
|
+
unsigned int write_pos = __sync_fetch_and_add( &external_callbacks->write_position, 1 ) % external_callbacks->size;
|
95
|
+
assert( __sync_bool_compare_and_swap( &( external_callbacks->buffer[ write_pos ] ), NULL, callback ) );
|
96
|
+
|
97
|
+
return true;
|
98
|
+
}
|
99
|
+
bool ( *push_external_callback )( external_callback_t callback ) = _push_external_callback;
|
100
|
+
|
101
|
+
|
102
|
+
static void
|
103
|
+
_run_external_callback() {
|
104
|
+
assert( external_callbacks != NULL );
|
105
|
+
assert( external_callbacks->buffer != NULL );
|
106
|
+
|
107
|
+
while ( external_callbacks->write_position != external_callbacks->read_position ) {
|
108
|
+
unsigned int read_pos = external_callbacks->read_position % external_callbacks->size;
|
109
|
+
external_callback_t callback = external_callbacks->buffer[ read_pos ];
|
110
|
+
assert( callback != NULL );
|
111
|
+
external_callbacks->buffer[ read_pos ] = NULL;
|
112
|
+
external_callbacks->read_position++;
|
113
|
+
debug( "run_external_callback: %p ( write_position = %u, read_position = %u )", callback,
|
114
|
+
external_callbacks->write_position, external_callbacks->read_position );
|
115
|
+
callback();
|
116
|
+
}
|
117
|
+
}
|
118
|
+
void ( *run_external_callback )() = _run_external_callback;
|
119
|
+
|
120
|
+
|
121
|
+
/*
|
122
|
+
* Local variables:
|
123
|
+
* c-basic-offset: 2
|
124
|
+
* indent-tabs-mode: nil
|
125
|
+
* End:
|
126
|
+
*/
|
@@ -0,0 +1,46 @@
|
|
1
|
+
/*
|
2
|
+
* External callback implementation
|
3
|
+
*
|
4
|
+
* Copyright (C) 2013 NEC Corporation
|
5
|
+
*
|
6
|
+
* This program is free software; you can redistribute it and/or modify
|
7
|
+
* it under the terms of the GNU General Public License, version 2, as
|
8
|
+
* published by the Free Software Foundation.
|
9
|
+
*
|
10
|
+
* This program is distributed in the hope that it will be useful,
|
11
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
* GNU General Public License for more details.
|
14
|
+
*
|
15
|
+
* You should have received a copy of the GNU General Public License along
|
16
|
+
* with this program; if not, write to the Free Software Foundation, Inc.,
|
17
|
+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
18
|
+
*/
|
19
|
+
|
20
|
+
|
21
|
+
#ifndef EXTERNAL_CALLBACK_H
|
22
|
+
#define EXTERNAL_CALLBACK_H
|
23
|
+
|
24
|
+
|
25
|
+
#include <sys/types.h>
|
26
|
+
#include "bool.h"
|
27
|
+
|
28
|
+
typedef void ( *external_callback_t )( void );
|
29
|
+
|
30
|
+
extern void ( *init_external_callback )( void );
|
31
|
+
extern void ( *finalize_external_callback )( void );
|
32
|
+
extern bool ( *push_external_callback )( external_callback_t callback );
|
33
|
+
extern void ( *run_external_callback )( void );
|
34
|
+
|
35
|
+
#define set_external_callback( callback ) push_external_callback( callback )
|
36
|
+
|
37
|
+
|
38
|
+
#endif // EXTERNAL_CALLBACK_H
|
39
|
+
|
40
|
+
|
41
|
+
/*
|
42
|
+
* Local variables:
|
43
|
+
* c-basic-offset: 2
|
44
|
+
* indent-tabs-mode: nil
|
45
|
+
* End:
|
46
|
+
*/
|
data/src/lib/messenger.c
CHANGED
@@ -141,6 +141,7 @@ enum {
|
|
141
141
|
MESSAGE_TYPE_NOTIFY,
|
142
142
|
MESSAGE_TYPE_REQUEST,
|
143
143
|
MESSAGE_TYPE_REPLY,
|
144
|
+
MESSAGE_TYPE_INVALID = 255,
|
144
145
|
};
|
145
146
|
|
146
147
|
typedef struct message_buffer {
|
@@ -172,6 +173,7 @@ typedef struct receive_queue {
|
|
172
173
|
struct sockaddr_un listen_addr;
|
173
174
|
dlist_element *client_sockets;
|
174
175
|
message_buffer *buffer;
|
176
|
+
bool in_progress;
|
175
177
|
} receive_queue;
|
176
178
|
|
177
179
|
typedef struct send_queue {
|
@@ -425,12 +427,14 @@ delete_receive_queue( void *service_name, void *_rq, void *user_data ) {
|
|
425
427
|
receive_queue_callback *cb;
|
426
428
|
|
427
429
|
assert( rq != NULL );
|
430
|
+
assert( rq->in_progress == false );
|
428
431
|
for ( element = rq->message_callbacks->next; element; element = element->next ) {
|
429
432
|
cb = element->data;
|
430
433
|
debug( "Deleting a callback ( function = %p, message_type = %#x ).", cb->function, cb->message_type );
|
431
434
|
xfree( cb );
|
432
435
|
}
|
433
436
|
delete_dlist( rq->message_callbacks );
|
437
|
+
rq->message_callbacks = NULL;
|
434
438
|
|
435
439
|
for ( element = rq->client_sockets->next; element; element = element->next ) {
|
436
440
|
client_socket = element->data;
|
@@ -591,6 +595,7 @@ create_receive_queue( const char *service_name ) {
|
|
591
595
|
rq->message_callbacks = create_dlist();
|
592
596
|
rq->client_sockets = create_dlist();
|
593
597
|
rq->buffer = create_message_buffer( messenger_recv_queue_length );
|
598
|
+
rq->in_progress = false;
|
594
599
|
|
595
600
|
insert_hash_entry( receive_queues, rq->service_name, rq );
|
596
601
|
|
@@ -699,11 +704,17 @@ delete_message_callback( const char *service_name, uint8_t message_type, void (
|
|
699
704
|
cb = e->data;
|
700
705
|
if ( ( cb->function == callback ) && ( cb->message_type == message_type ) ) {
|
701
706
|
debug( "Deleting a callback ( message_type = %#x, callback = %p ).", message_type, callback );
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
+
if ( rq->in_progress ) {
|
708
|
+
cb->function = NULL;
|
709
|
+
cb->message_type = MESSAGE_TYPE_INVALID;
|
710
|
+
}
|
711
|
+
else {
|
712
|
+
xfree( cb );
|
713
|
+
delete_dlist_element( e );
|
714
|
+
if ( rq->message_callbacks->next == NULL ) {
|
715
|
+
debug( "No more callback for message_type = %#x.", message_type );
|
716
|
+
delete_receive_queue( rq->service_name, rq, NULL );
|
717
|
+
}
|
707
718
|
}
|
708
719
|
return true;
|
709
720
|
}
|
@@ -844,17 +855,15 @@ send_queue_connect( send_queue *sq ) {
|
|
844
855
|
return -1;
|
845
856
|
}
|
846
857
|
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
return -1;
|
855
|
-
}
|
858
|
+
sq->socket_buffer_size = 1048576;
|
859
|
+
int ret = setsockopt( sq->server_socket, SOL_SOCKET, SO_SNDBUF, ( const void * ) &sq->socket_buffer_size, ( socklen_t ) sizeof( sq->socket_buffer_size ) );
|
860
|
+
if ( ret < 0 ) {
|
861
|
+
error( "Failed to set SO_SNDBUF to %d ( %s [%d] ).", sq->socket_buffer_size, strerror( errno ), errno );
|
862
|
+
close( sq->server_socket );
|
863
|
+
sq->server_socket = -1;
|
864
|
+
return -1;
|
856
865
|
}
|
857
|
-
|
866
|
+
ret = fcntl( sq->server_socket, F_SETFL, O_NONBLOCK );
|
858
867
|
if ( ret < 0 ) {
|
859
868
|
error( "Failed to set O_NONBLOCK ( %s [%d] ).", strerror( errno ), errno );
|
860
869
|
close( sq->server_socket );
|
@@ -873,7 +882,7 @@ send_queue_connect( send_queue *sq ) {
|
|
873
882
|
return 0;
|
874
883
|
}
|
875
884
|
|
876
|
-
set_fd_handler( sq->server_socket, on_send_read, sq,
|
885
|
+
set_fd_handler( sq->server_socket, on_send_read, sq, on_send_write, sq );
|
877
886
|
set_readable( sq->server_socket, true );
|
878
887
|
|
879
888
|
if ( sq->buffer != NULL && sq->buffer->data_length >= sizeof( message_header ) ) {
|
@@ -1092,9 +1101,7 @@ push_message_to_send_queue( const char *service_name, const uint8_t message_type
|
|
1092
1101
|
}
|
1093
1102
|
|
1094
1103
|
set_writable( sq->server_socket, true );
|
1095
|
-
|
1096
|
-
on_send_write( sq->server_socket, sq );
|
1097
|
-
}
|
1104
|
+
|
1098
1105
|
return true;
|
1099
1106
|
}
|
1100
1107
|
|
@@ -1215,7 +1222,7 @@ _clear_send_queue( const char *service_name ) {
|
|
1215
1222
|
return false;
|
1216
1223
|
}
|
1217
1224
|
|
1218
|
-
if ( sq->
|
1225
|
+
if ( sq->server_socket > -1 ) {
|
1219
1226
|
set_writable( sq->server_socket, false );
|
1220
1227
|
}
|
1221
1228
|
|
@@ -1369,14 +1376,13 @@ truncate_message_buffer( message_buffer *buf, size_t len ) {
|
|
1369
1376
|
len = buf->data_length;
|
1370
1377
|
}
|
1371
1378
|
|
1372
|
-
|
1373
|
-
|
1379
|
+
buf->data_length -= len;
|
1380
|
+
if ( buf->data_length == 0 ) {
|
1381
|
+
buf->head_offset = 0;
|
1374
1382
|
}
|
1375
1383
|
else {
|
1376
|
-
|
1377
|
-
buf->head_offset = 0;
|
1384
|
+
buf->head_offset += len;
|
1378
1385
|
}
|
1379
|
-
buf->data_length -= len;
|
1380
1386
|
}
|
1381
1387
|
|
1382
1388
|
|
@@ -1437,15 +1443,18 @@ static void
|
|
1437
1443
|
call_message_callbacks( receive_queue *rq, const uint8_t message_type, const uint16_t tag, void *data, size_t len ) {
|
1438
1444
|
assert( rq != NULL );
|
1439
1445
|
|
1440
|
-
dlist_element *element;
|
1446
|
+
dlist_element *element, *next;
|
1441
1447
|
receive_queue_callback *cb;
|
1442
1448
|
|
1443
1449
|
debug( "Calling message callbacks ( service_name = %s, message_type = %#x, tag = %#x, data = %p, len = %zu ).",
|
1444
1450
|
rq->service_name, message_type, tag, data, len );
|
1445
1451
|
|
1446
|
-
|
1452
|
+
assert( rq->in_progress != true );
|
1453
|
+
rq->in_progress = true;
|
1454
|
+
for ( element = rq->message_callbacks->next; element; element = next ) {
|
1455
|
+
next = element->next;
|
1447
1456
|
cb = element->data;
|
1448
|
-
if ( cb->message_type != message_type ) {
|
1457
|
+
if ( cb == NULL || cb->function == NULL || cb->message_type != message_type ) {
|
1449
1458
|
continue;
|
1450
1459
|
}
|
1451
1460
|
switch ( message_type ) {
|
@@ -1511,6 +1520,19 @@ call_message_callbacks( receive_queue *rq, const uint8_t message_type, const uin
|
|
1511
1520
|
assert( 0 );
|
1512
1521
|
}
|
1513
1522
|
}
|
1523
|
+
for ( element = rq->message_callbacks->next; element; element = next ) {
|
1524
|
+
next = element->next;
|
1525
|
+
cb = element->data;
|
1526
|
+
if ( cb->function == NULL ) {
|
1527
|
+
xfree( cb );
|
1528
|
+
delete_dlist_element( element );
|
1529
|
+
}
|
1530
|
+
}
|
1531
|
+
rq->in_progress = false;
|
1532
|
+
if ( rq->message_callbacks->next == NULL ) {
|
1533
|
+
debug( "No more callback for message_type = %#x.", message_type );
|
1534
|
+
delete_receive_queue( rq->service_name, rq, NULL );
|
1535
|
+
}
|
1514
1536
|
}
|
1515
1537
|
|
1516
1538
|
|
@@ -1648,11 +1670,6 @@ on_send_write( int fd, void *data ) {
|
|
1648
1670
|
debug( "Sending data to remote ( fd = %d, service_name = %s, buffer = %p, data_length = %zu ).",
|
1649
1671
|
fd, sq->service_name, get_message_buffer_head( sq->buffer ), sq->buffer->data_length );
|
1650
1672
|
|
1651
|
-
if ( sq->buffer->data_length < sizeof( message_header ) ) {
|
1652
|
-
set_writable( sq->server_socket, false );
|
1653
|
-
return;
|
1654
|
-
}
|
1655
|
-
|
1656
1673
|
void *send_data;
|
1657
1674
|
size_t send_len;
|
1658
1675
|
ssize_t sent_len;
|
@@ -1664,8 +1681,14 @@ on_send_write( int fd, void *data ) {
|
|
1664
1681
|
if ( sent_len == -1 ) {
|
1665
1682
|
int err = errno;
|
1666
1683
|
if ( err != EAGAIN && err != EWOULDBLOCK ) {
|
1667
|
-
|
1668
|
-
|
1684
|
+
if ( err == EPIPE ) {
|
1685
|
+
debug( "Failed to send ( service_name = %s, fd = %d, errno = %s [%d] ).",
|
1686
|
+
sq->service_name, fd, strerror( err ), err );
|
1687
|
+
}
|
1688
|
+
else {
|
1689
|
+
error( "Failed to send ( service_name = %s, fd = %d, errno = %s [%d] ).",
|
1690
|
+
sq->service_name, fd, strerror( err ), err );
|
1691
|
+
}
|
1669
1692
|
send_dump_message( MESSENGER_DUMP_SEND_CLOSED, sq->service_name, NULL, 0 );
|
1670
1693
|
|
1671
1694
|
set_readable( sq->server_socket, false );
|